Преглед изворни кода

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

# Conflicts:
#	dist/preview release/babylon.d.ts
#	dist/preview release/babylon.js
#	dist/preview release/babylon.max.js
#	dist/preview release/babylon.module.d.ts
#	dist/preview release/babylon.worker.js
#	dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
#	dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
#	dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
#	dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
#	dist/preview release/inspector/babylon.inspector.bundle.js
#	dist/preview release/inspector/babylon.inspector.d.ts
#	dist/preview release/inspector/babylon.inspector.js
#	dist/preview release/inspector/babylon.inspector.min.js
#	dist/preview release/loaders/babylon.glTF1FileLoader.min.js
#	dist/preview release/loaders/babylon.glTF2FileLoader.js
#	dist/preview release/loaders/babylon.glTF2FileLoader.min.js
#	dist/preview release/loaders/babylon.glTFFileLoader.js
#	dist/preview release/loaders/babylon.glTFFileLoader.min.js
#	dist/preview release/loaders/babylonjs.loaders.js
#	dist/preview release/loaders/babylonjs.loaders.min.js
David Rousset пре 7 година
родитељ
комит
8b8b2398a2
100 измењених фајлова са 94039 додато и 68620 уклоњено
  1. BIN
      Playground/LogoPBT.png
  2. 21112 15435
      Playground/babylon.d.txt
  3. 27 0
      Playground/css/index.css
  4. 1 0
      Playground/debug.html
  5. 50 72
      Playground/full.html
  6. 1 0
      Playground/index-local.html
  7. 406 330
      Playground/index.html
  8. 1 0
      Playground/indexStable.html
  9. 2 0
      Playground/js/index.js
  10. 432 0
      Playground/js/pbt.js
  11. 14 0
      Playground/package-lock.json
  12. 6 0
      Tools/Gulp/config.json
  13. 14 4
      Tools/Gulp/gulpfile.js
  14. BIN
      Viewer/assets/img/close.png
  15. BIN
      Viewer/assets/img/fullscreen.png
  16. BIN
      Viewer/assets/img/help-circle.png
  17. BIN
      Viewer/assets/img/loading.png
  18. 210 0
      Viewer/assets/pep.min.js
  19. 2 2
      Viewer/assets/templates/default/navbar.html
  20. 2 4
      Viewer/dist/domExample.html
  21. 5622 7086
      Viewer/dist/viewer.js
  22. 38 0
      Viewer/dist/viewer.min.js
  23. 9 11
      Viewer/package.json
  24. 3 5
      Viewer/src/configuration/configuration.ts
  25. 4 4
      Viewer/src/configuration/loader.ts
  26. 0 2
      Viewer/src/configuration/mappers.ts
  27. 8 12
      Viewer/src/configuration/types/default.ts
  28. 3 1
      Viewer/src/index.ts
  29. 15 1
      Viewer/src/templateManager.ts
  30. 6 4
      Viewer/src/viewer/defaultViewer.ts
  31. 4 0
      Viewer/src/viewer/viewerManager.ts
  32. 9 15
      Viewer/webpack.config.js
  33. 11192 11158
      dist/preview release/babylon.d.ts
  34. 52 0
      dist/preview release/babylon.js
  35. 250 166
      dist/preview release/babylon.max.js
  36. 11192 11158
      dist/preview release/babylon.module.d.ts
  37. 53 1
      dist/preview release/babylon.worker.js
  38. 21636 11715
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  39. 58 1
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  40. 271 167
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  41. 20458 10689
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
  42. 8 2
      dist/preview release/gui/babylon.gui.js
  43. 3 3
      dist/preview release/gui/babylon.gui.min.js
  44. 267 260
      dist/preview release/inspector/babylon.inspector.bundle.js
  45. 11 0
      dist/preview release/inspector/babylon.inspector.d.ts
  46. 12 1
      dist/preview release/inspector/babylon.inspector.js
  47. 8 1
      dist/preview release/inspector/babylon.inspector.min.js
  48. 6 1
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  49. 3 0
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  50. 31 0
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  51. 6 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  52. 3 0
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  53. 31 0
      dist/preview release/loaders/babylon.glTFFileLoader.js
  54. 7 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  55. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  56. 31 0
      dist/preview release/loaders/babylonjs.loaders.js
  57. 7 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  58. 3 0
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  59. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  60. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  61. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  62. 3 3
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  63. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  64. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  65. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  66. 3 0
      dist/preview release/what's new.md
  67. 6 2
      gui/src/advancedDynamicTexture.ts
  68. 5 1
      gui/src/controls/container.ts
  69. 2 2
      inspector/src/adapters/MeshAdapter.ts
  70. 8 0
      inspector/src/properties.ts
  71. 28 1
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  72. 1 2
      package.json
  73. 0 5
      src/Audio/babylon.sound.ts
  74. 1 1
      src/Behaviors/Cameras/babylon.bouncingBehavior.ts
  75. 37 1
      src/Behaviors/Cameras/babylon.framingBehavior.ts
  76. 2 2
      src/Collisions/babylon.collisionCoordinator.ts
  77. 2 2
      src/Culling/Octrees/babylon.octree.ts
  78. 16 6
      src/Culling/babylon.ray.ts
  79. 1 1
      src/Engine/babylon.engine.ts
  80. 2 2
      src/Helpers/babylon.environmentHelper.ts
  81. 0 5
      src/Lights/babylon.directionalLight.ts
  82. 6 6
      src/Loading/babylon.sceneLoader.ts
  83. 20 7
      src/Math/babylon.math.ts
  84. 4 14
      src/Mesh/babylon.abstractMesh.ts
  85. 1 7
      src/Mesh/babylon.instancedMesh.ts
  86. 10 3
      src/Mesh/babylon.linesMesh.ts
  87. 0 8
      src/Mesh/babylon.mesh.ts
  88. 10 2
      src/Mesh/babylon.mesh.vertexData.ts
  89. 38 15
      src/Mesh/babylon.meshBuilder.ts
  90. 3 11
      src/Mesh/babylon.subMesh.ts
  91. 1 3
      src/Particles/babylon.solidParticleSystem.ts
  92. 2 2
      src/Physics/Plugins/babylon.cannonJSPlugin.ts
  93. 2 10
      src/Physics/babylon.physicsImpostor.ts
  94. 2 2
      src/Rendering/babylon.depthRenderer.ts
  95. 1 1
      src/Rendering/babylon.renderingGroup.ts
  96. 68 48
      src/Tools/babylon.tools.ts
  97. 147 124
      src/babylon.scene.ts
  98. BIN
      tests/validation/ReferenceImages/gltfMaterial.png
  99. BIN
      tests/validation/ReferenceImages/gltfMaterialAlpha.png
  100. 0 0
      tests/validation/ReferenceImages/gltfMaterialMetallicRoughness.png

BIN
Playground/LogoPBT.png


Разлика између датотеке није приказан због своје велике величине
+ 21112 - 15435
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>
 

+ 50 - 72
Playground/full.html

@@ -1,77 +1,55 @@
 <!DOCTYPE html>
 <html>
 
-<head>
-    <title>Babylon.js Playground</title>
-    <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
-	<link rel="apple-touch-icon" sizes="57x57" href="https://www.babylonjs.com/img/favicon/apple-icon-57x57.png">
-	<link rel="apple-touch-icon" sizes="60x60" href="https://www.babylonjs.com/img/favicon/apple-icon-60x60.png">
-	<link rel="apple-touch-icon" sizes="72x72" href="https://www.babylonjs.com/img/favicon/apple-icon-72x72.png">
-	<link rel="apple-touch-icon" sizes="76x76" href="https://www.babylonjs.com/img/favicon/apple-icon-76x76.png">
-	<link rel="apple-touch-icon" sizes="114x114" href="https://www.babylonjs.com/img/favicon/apple-icon-114x114.png">
-	<link rel="apple-touch-icon" sizes="120x120" href="https://www.babylonjs.com/img/favicon/apple-icon-120x120.png">
-	<link rel="apple-touch-icon" sizes="144x144" href="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png">
-	<link rel="apple-touch-icon" sizes="152x152" href="https://www.babylonjs.com/img/favicon/apple-icon-152x152.png">
-	<link rel="apple-touch-icon" sizes="180x180" href="https://www.babylonjs.com/img/favicon/apple-icon-180x180.png">
-	<link rel="icon" type="image/png" sizes="192x192"  href="https://www.babylonjs.com/img/favicon/android-icon-192x192.png">
-	<link rel="icon" type="image/png" sizes="32x32" href="https://www.babylonjs.com/img/favicon/favicon-32x32.png">
-	<link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
-	<link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
-	<link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
-	<meta name="msapplication-TileColor" content="#ffffff">
-	<meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
-	<meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
-	<meta name="theme-color" content="#ffffff">
-
-    <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
-    <!-- Babylon.js -->
-    <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/Oimo.js"></script>
-    <script src="https://preview.babylonjs.com/babylon.js"></script>    
-    <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
-
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.fireMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.waterMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.lavaMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.normalMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.skyMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.triPlanarMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.terrainMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gradientMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.fireProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.grassProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.marbleProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.roadProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.starfieldProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.woodProceduralTexture.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.asciiArtPostProcess.min.js"></script>
-    <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.digitalRainPostProcess.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/loaders/babylon.glTFFileLoader.js"></script>
-    <script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
-    <script src="https://preview.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
-
-    <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
-    
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>    
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/canvas2D/dist/preview%20release/babylon.canvas2d.min.js"></script>
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>
-    <link href="frame.css" rel="stylesheet" />
-</head>
-
-<body>
-    <canvas touch-action="none" id="renderCanvas" tabindex="1"></canvas>
-    <script src="https://code.jquery.com/jquery.js"></script>
-    <script src="js/frame.js"></script>
-</body>
+    <head>
+        <title>Babylon.js Playground</title>
+        <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
+        <link rel="apple-touch-icon" sizes="57x57" href="https://www.babylonjs.com/img/favicon/apple-icon-57x57.png">
+        <link rel="apple-touch-icon" sizes="60x60" href="https://www.babylonjs.com/img/favicon/apple-icon-60x60.png">
+        <link rel="apple-touch-icon" sizes="72x72" href="https://www.babylonjs.com/img/favicon/apple-icon-72x72.png">
+        <link rel="apple-touch-icon" sizes="76x76" href="https://www.babylonjs.com/img/favicon/apple-icon-76x76.png">
+        <link rel="apple-touch-icon" sizes="114x114" href="https://www.babylonjs.com/img/favicon/apple-icon-114x114.png">
+        <link rel="apple-touch-icon" sizes="120x120" href="https://www.babylonjs.com/img/favicon/apple-icon-120x120.png">
+        <link rel="apple-touch-icon" sizes="144x144" href="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png">
+        <link rel="apple-touch-icon" sizes="152x152" href="https://www.babylonjs.com/img/favicon/apple-icon-152x152.png">
+        <link rel="apple-touch-icon" sizes="180x180" href="https://www.babylonjs.com/img/favicon/apple-icon-180x180.png">
+        <link rel="icon" type="image/png" sizes="192x192" href="https://www.babylonjs.com/img/favicon/android-icon-192x192.png">
+        <link rel="icon" type="image/png" sizes="32x32" href="https://www.babylonjs.com/img/favicon/favicon-32x32.png">
+        <link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
+        <link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
+        <link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
+        <meta name="msapplication-TileColor" content="#ffffff">
+        <meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
+        <meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
+        <meta name="theme-color" content="#ffffff">
+
+        <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
+        <!-- Babylon.js -->
+        <script src="https://preview.babylonjs.com/cannon.js"></script>
+        <script src="https://preview.babylonjs.com/Oimo.js"></script>
+        <script src="https://preview.babylonjs.com/babylon.js"></script>
+        <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
+
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
+
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
+
+        <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
+
+        <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
+
+        <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
+
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/canvas2D/dist/preview%20release/babylon.canvas2d.min.js"></script>
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>
+        <link href="frame.css" rel="stylesheet" />
+    </head>
+
+    <body>
+        <canvas touch-action="none" id="renderCanvas" tabindex="1"></canvas>
+        <script src="https://code.jquery.com/jquery.js"></script>
+        <script src="js/frame.js"></script>
+    </body>
 
 </html>

+ 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();

+ 406 - 330
Playground/index.html

@@ -1,414 +1,490 @@
 <!DOCTYPE html>
 <html>
 
-<head>
-    <title>Babylon.js Playground</title>
-    <meta charset='utf-8' />
-    <meta name="viewport" content="width=device-width, user-scalable=no">
-    <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
-	<link rel="apple-touch-icon" sizes="57x57" href="https://www.babylonjs.com/img/favicon/apple-icon-57x57.png">
-	<link rel="apple-touch-icon" sizes="60x60" href="https://www.babylonjs.com/img/favicon/apple-icon-60x60.png">
-	<link rel="apple-touch-icon" sizes="72x72" href="https://www.babylonjs.com/img/favicon/apple-icon-72x72.png">
-	<link rel="apple-touch-icon" sizes="76x76" href="https://www.babylonjs.com/img/favicon/apple-icon-76x76.png">
-	<link rel="apple-touch-icon" sizes="114x114" href="https://www.babylonjs.com/img/favicon/apple-icon-114x114.png">
-	<link rel="apple-touch-icon" sizes="120x120" href="https://www.babylonjs.com/img/favicon/apple-icon-120x120.png">
-	<link rel="apple-touch-icon" sizes="144x144" href="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png">
-	<link rel="apple-touch-icon" sizes="152x152" href="https://www.babylonjs.com/img/favicon/apple-icon-152x152.png">
-	<link rel="apple-touch-icon" sizes="180x180" href="https://www.babylonjs.com/img/favicon/apple-icon-180x180.png">
-	<link rel="icon" type="image/png" sizes="192x192"  href="https://www.babylonjs.com/img/favicon/android-icon-192x192.png">
-	<link rel="icon" type="image/png" sizes="32x32" href="https://www.babylonjs.com/img/favicon/favicon-32x32.png">
-	<link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
-	<link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
-	<link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
-	<meta name="msapplication-TileColor" content="#ffffff">
-	<meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
-	<meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
-	<meta name="theme-color" content="#ffffff">
-    
-    <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
-    <!--For canvas/code separator-->
-    <script src="js/libs/split.js"></script>
-
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
-    <!-- jszip -->
-    <script src="js/libs/jszip.min.js"></script>
-    <script src="js/libs/fileSaver.js"></script>
-    <!--Monaco-->
-    <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
-    <!-- Babylon.js -->
-    <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/Oimo.js"></script>
-    <script src="https://preview.babylonjs.com/babylon.js"></script>    
-    <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
-
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.fireMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.waterMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.lavaMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.normalMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.skyMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.triPlanarMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.terrainMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gradientMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.fireProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.grassProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.marbleProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.roadProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.starfieldProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.woodProceduralTexture.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.asciiArtPostProcess.min.js"></script>
-    <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.digitalRainPostProcess.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/loaders/babylon.glTFFileLoader.js"></script>
-    <script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
-    <script src="https://preview.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
-
-    <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
-
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/canvas2D/dist/preview%20release/babylon.canvas2d.min.js"></script>
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>
-    <link href="css/index.css" rel="stylesheet" />
-</head>
-
-<body>
-    <div class="navbar navBar1600">
-        <div class="title">
-            Babylon.js Playground
-        </div>
-        <div class="version" id="mainTitle">
-        </div>
+    <head>
+        <title>Babylon.js Playground</title>
+        <meta charset='utf-8' />
+        <meta name="viewport" content="width=device-width, user-scalable=no">
+        <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
+        <link rel="apple-touch-icon" sizes="57x57" href="https://www.babylonjs.com/img/favicon/apple-icon-57x57.png">
+        <link rel="apple-touch-icon" sizes="60x60" href="https://www.babylonjs.com/img/favicon/apple-icon-60x60.png">
+        <link rel="apple-touch-icon" sizes="72x72" href="https://www.babylonjs.com/img/favicon/apple-icon-72x72.png">
+        <link rel="apple-touch-icon" sizes="76x76" href="https://www.babylonjs.com/img/favicon/apple-icon-76x76.png">
+        <link rel="apple-touch-icon" sizes="114x114" href="https://www.babylonjs.com/img/favicon/apple-icon-114x114.png">
+        <link rel="apple-touch-icon" sizes="120x120" href="https://www.babylonjs.com/img/favicon/apple-icon-120x120.png">
+        <link rel="apple-touch-icon" sizes="144x144" href="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png">
+        <link rel="apple-touch-icon" sizes="152x152" href="https://www.babylonjs.com/img/favicon/apple-icon-152x152.png">
+        <link rel="apple-touch-icon" sizes="180x180" href="https://www.babylonjs.com/img/favicon/apple-icon-180x180.png">
+        <link rel="icon" type="image/png" sizes="192x192" href="https://www.babylonjs.com/img/favicon/android-icon-192x192.png">
+        <link rel="icon" type="image/png" sizes="32x32" href="https://www.babylonjs.com/img/favicon/favicon-32x32.png">
+        <link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
+        <link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
+        <link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
+        <meta name="msapplication-TileColor" content="#ffffff">
+        <meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
+        <meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
+        <meta name="theme-color" content="#ffffff">
+
+        <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
+        <!--For canvas/code separator-->
+        <script src="js/libs/split.js"></script>
+
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
+        <!-- jszip -->
+        <script src="js/libs/jszip.min.js"></script>
+        <script src="js/libs/fileSaver.js"></script>
+        <!--Monaco-->
+        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
+        <!-- Babylon.js -->
+        <script src="https://preview.babylonjs.com/cannon.js"></script>
+        <script src="https://preview.babylonjs.com/Oimo.js"></script>
+        <script src="https://preview.babylonjs.com/babylon.js"></script>
+        <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
+
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
+
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
+
+        <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
+
+        <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
+
+        <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
+
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/canvas2D/dist/preview%20release/babylon.canvas2d.min.js"></script>
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>
+        <link href="css/index.css" rel="stylesheet" />
+    </head>
+
+    <body>
+        <div class="navbar navBar1600">
+            <div class="title">
+                Babylon.js Playground
+            </div>
+            <div class="version" id="mainTitle">
+            </div>
 
-        <div class="category">
-            <div class="button run" id="runButton1600">Run <i class="fa fa-play" aria-hidden="true"></i></div>
-        </div>
+            <div class="category">
+                <div class="button run" id="runButton1600">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
+            </div>
 
 
-        <div class="category">
-            <div class="button" id="newButton1600">New<i class="fa fa-file" aria-hidden="true"></i></div>
-            <div class="button removeOnPhone" id="clearButton1600">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
-        </div>
+            <div class="category">
+                <div class="button" id="newButton1600">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1600">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
+            </div>
 
-        <div class="category">
-            <div class="button" id="saveButton1600">Save <i class="fa fa-floppy-o" aria-hidden="true"></i></div>
-            <div class="button removeOnPhone" id="zipButton1600">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
-        </div>
+            <div class="category">
+                <div class="button" id="saveButton1600">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1600">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
+            </div>
 
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme1600">Dark</div>
-                            <div class="option" id="lightTheme1600">Light</div>
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1600">Dark</div>
+                                <div class="option" id="lightTheme1600">Light</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option subSelect"><span id="currentFontSize1600">Font: 14</span><i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1600">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
                         </div>
+                        <div class="option" id="safemodeToggle1600">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1600">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1600">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1600">Format code</div>
                     </div>
-                    <div class="option" id="safemodeToggle1600">Safe mode <i class="fa fa-square-o" aria-hidden="true"></i></div>
-                    <div class="option checked" id="editorButton1600">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton1600">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
-                    <div class="option" id="formatButton1600">Format code</div>
                 </div>
-            </div>
 
-            <div class="button uncheck" id="debugButton1600">Debug layer <i class="fa fa-square-o" aria-hidden="true"></i></div>
-            <div class="button" id="metadataButton1600">Metadata</div>
-        </div>
+                <div class="button uncheck" id="debugButton1600">Debug layer
+                    <i class="fa fa-square-o" aria-hidden="true"></i>
+                </div>
+                <div class="button" id="metadataButton1600">Metadata</div>
+            </div>
 
 
 
-        <div class="category right">
-            <div class="button select"><span id="currentVersion1600">Version: Latest</span>
-                <div class="toDisplay">
-                    <div class="option" onclick="setVersion('latest');">Latest</div>
-                    <div class="option" onclick="setVersion('stable');">Stable</div>
+            <div class="category right">
+                <div class="button select">
+                    <span id="currentVersion1600">Version: Latest</span>
+                    <div class="toDisplay">
+                        <div class="option" onclick="setVersion('latest');">Latest</div>
+                        <div class="option" onclick="setVersion('stable');">Stable</div>
+                    </div>
                 </div>
-            </div>
-            <div class="button select"> <span id="currentScript1600">Scenes</span>
-                <div class="toDisplayBig">
-                    <ul id="scriptsList1600">
-                    </ul>
+                <div class="button select">
+                    <span id="currentScript1600">Scenes</span>
+                    <div class="toDisplayBig">
+                        <ul id="scriptsList1600">
+                        </ul>
+                    </div>
                 </div>
             </div>
+            <div class="save-message" id="saveMessage">
+                This PG has missing metadata. Click save to add them.
+            </div>
         </div>
-        <div class="save-message" id="saveMessage">
-            This PG has missing metadata. Click save to add them.
-        </div>
-    </div>
 
-    <div class="navbar navBar1475">
-        <div class="title">
-            Babylon.js Playground
-        </div>
-        <div class="version" id="mainTitle">
-        </div>
+        <div class="navbar navBar1475">
+            <div class="title">
+                Babylon.js Playground
+            </div>
+            <div class="version" id="mainTitle">
+            </div>
 
-        <div class="category">
-            <div class="button run" id="runButton1475">Run <i class="fa fa-play" aria-hidden="true"></i></div>
-        </div>
+            <div class="category">
+                <div class="button run" id="runButton1475">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
+            </div>
 
 
-        <div class="category">
-            <div class="button" id="newButton1475">New<i class="fa fa-file" aria-hidden="true"></i></div>
-            <div class="button removeOnPhone" id="clearButton1475">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
-        </div>
+            <div class="category">
+                <div class="button" id="newButton1475">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1475">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
+            </div>
 
-        <div class="category">
-            <div class="button" id="saveButton1475">Save <i class="fa fa-floppy-o" aria-hidden="true"></i></div>
-            <div class="button removeOnPhone" id="zipButton1475">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
-        </div>
+            <div class="category">
+                <div class="button" id="saveButton1475">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1475">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
+            </div>
 
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme1475">Dark</div>
-                            <div class="option" id="lightTheme1475">Light</div>
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1475">Dark</div>
+                                <div class="option" id="lightTheme1475">Light</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option subSelect"><span id="currentFontSize1475">Font: 14</span><i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1475">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option" id='safemodeToggle1475'>Safe mode <i class="fa fa-square-o" aria-hidden="true"></i></div>
-                    <div class="option checked" id="editorButton1475">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton1475">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
-                    <div class="option" id="formatButton1475">Format code</div>
-                    <div class="option" id="debugButton1475">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
-                    <div class="option" id="metadataButton1475">Metadata</div>
-                    <div class="option subSelect"><span id="currentVersion1475">Vers. : Latest</span><i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setVersion('latest');">Latest</div>
-                            <div class="option" onclick="setVersion('stable');">Stable</div>
+                        <div class="option" id='safemodeToggle1475'>Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1475">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1475">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1475">Format code</div>
+                        <div class="option" id="debugButton1475">Debug layer
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton1475">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion1475">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('stable');">Stable</div>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <div class="category right">
-            <div class="button select"> <span id="currentScript1475">Scenes</span>
-                <div class="toDisplayBig">
-                    <ul id="scriptsList1475">
-                    </ul>
+            <div class="category right">
+                <div class="button select">
+                    <span id="currentScript1475">Scenes</span>
+                    <div class="toDisplayBig">
+                        <ul id="scriptsList1475">
+                        </ul>
+                    </div>
                 </div>
             </div>
+            <div class="save-message" id="saveMessage">
+                This PG has missing metadata. Click save to add them.
+            </div>
         </div>
-        <div class="save-message" id="saveMessage">
-            This PG has missing metadata. Click save to add them.
-        </div>
-    </div>
 
-    <div class="navbar navBar1030">
-        <div class="category">
-            <div class="button run" id="runButton1030">Run <i class="fa fa-play" aria-hidden="true"></i></div>
-        </div>
+        <div class="navbar navBar1030">
+            <div class="category">
+                <div class="button run" id="runButton1030">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
+            </div>
 
 
-        <div class="category">
-            <div class="button" id="newButton1030">New<i class="fa fa-file" aria-hidden="true"></i></div>
-            <div class="button removeOnPhone" id="clearButton1030">Clear<i class="fa fa-trash" aria-hidden="true"></i></div>
-        </div>
+            <div class="category">
+                <div class="button" id="newButton1030">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1030">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
+            </div>
 
-        <div class="category">
-            <div class="button" id="saveButton1030">Save <i class="fa fa-floppy-o" aria-hidden="true"></i></div>
-            <div class="button removeOnPhone" id="zipButton1030">Zip<i class="fa fa-download" aria-hidden="true"></i></div>
-        </div>
+            <div class="category">
+                <div class="button" id="saveButton1030">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1030">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
+            </div>
 
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme1030">Dark</div>
-                            <div class="option" id="lightTheme1030">Light</div>
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1030">Dark</div>
+                                <div class="option" id="lightTheme1030">Light</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option subSelect"><span id="currentFontSize1030">Font: 14</span><i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1030">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option" id="safemodeToggle1030">Safe mode <i class="fa fa-square-o" aria-hidden="true"></i></div>
-                    <div class="option checked" id="editorButton1030">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton1030">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
-                    <div class="option" id="formatButton1030">Format code</div>
-                    <div class="option" id="debugButton1030">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
-                    <div class="option" id="metadataButton1030">Metadata</div>
-                    <div class="option subSelect"><span id="currentVersion1030">Vers. : Latest</span><i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setVersion('latest');">Latest</div>
-                            <div class="option" onclick="setVersion('stable');">Stable</div>
+                        <div class="option" id="safemodeToggle1030">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1030">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1030">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1030">Format code</div>
+                        <div class="option" id="debugButton1030">Debug layer
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton1030">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion1030">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('stable');">Stable</div>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <div class="category right">
-            <div class="button select"> <span id="currentScript1030">Scenes</span>
-                <div class="toDisplayBig">
-                    <ul id="scriptsList1030">
-                    </ul>
+            <div class="category right">
+                <div class="button select">
+                    <span id="currentScript1030">Scenes</span>
+                    <div class="toDisplayBig">
+                        <ul id="scriptsList1030">
+                        </ul>
+                    </div>
                 </div>
             </div>
-        </div>
-        <div class="save-message" id="saveMessage">
-            This PG has missing metadata. Click save to add them.
-        </div>
-    </div>
-
-    <div class="navbar navBar750">
-        <div class="category">
-            <div class="button select">File
-                <div class="toDisplay">
-                    <div class="option" id="runButton750">Run <i class="fa fa-play" aria-hidden="true"></i></div>
-                    <div class="option" id="newButton750">New <i class="fa fa-file" aria-hidden="true"></i></div>
-                    <div class="option" id="clearButton750">Clear <i class="fa fa-trash" aria-hidden="true"></i></div>
-                    <div class="option" id="saveButton750">Save <i class="fa fa-floppy-o" aria-hidden="true"></i></div>
-                    <div class="option" id="zipButton750">Zip <i class="fa fa-download" aria-hidden="true"></i></div>
-                </div>
+            <div class="save-message" id="saveMessage">
+                This PG has missing metadata. Click save to add them.
             </div>
         </div>
 
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme750">Dark</div>
-                            <div class="option" id="lightTheme750">Light</div>
+        <div class="navbar navBar750">
+            <div class="category">
+                <div class="button select">File
+                    <div class="toDisplay">
+                        <div class="option" id="runButton750">Run
+                            <i class="fa fa-play" aria-hidden="true"></i>
                         </div>
-                    </div>
-                    <div class="option subSelect"><span id="currentFontSize750">Font: 14</span><i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                        <div class="option" id="newButton750">New
+                            <i class="fa fa-file" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="clearButton750">Clear
+                            <i class="fa fa-trash" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="saveButton750">Save
+                            <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="zipButton750">Zip
+                            <i class="fa fa-download" aria-hidden="true"></i>
                         </div>
                     </div>
-                    <div class="option" id="safemodeToggle750">Safe mode <i class="fa fa-square-o" aria-hidden="true"></i></div>
-                    <div style="display:none;" class="option checked" id="editorButton750">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton750">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
-                    <div class="option" id="formatButton750">Format code</div>
-                    <div class="option" id="debugButton750">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
-                    <div class="option" id="metadataButton750">Metadata</div>
-                    <div class="option subSelect"><span id="currentVersion750">Vers. : Latest</span><i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setVersion('latest');">Latest</div>
-                            <div class="option" onclick="setVersion('stable');">Stable</div>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme750">Dark</div>
+                                <div class="option" id="lightTheme750">Light</div>
+                            </div>
+                        </div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize750">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
+                        </div>
+                        <div class="option" id="safemodeToggle750">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div style="display:none;" class="option checked" id="editorButton750">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton750">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
+                        <div class="option" id="formatButton750">Format code</div>
+                        <div class="option" id="debugButton750">Debug layer
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton750">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion750">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('stable');">Stable</div>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <div class="category right">
-            <div class="button select"> <span id="currentScript750">Scenes</span>
-                <div class="toDisplayBig">
-                    <ul id="scriptsList750">
-                    </ul>
+            <div class="category right">
+                <div class="button select">
+                    <span id="currentScript750">Scenes</span>
+                    <div class="toDisplayBig">
+                        <ul id="scriptsList750">
+                        </ul>
+                    </div>
                 </div>
             </div>
+            <div class="save-message" id="saveMessage">
+                This PG has missing metadata. Click save to add them.
+            </div>
         </div>
-        <div class="save-message" id="saveMessage">
-            This PG has missing metadata. Click save to add them.
-        </div>
-    </div>
 
-    <div class="wrapper">
-        <div id="jsEditor"></div>
-        <div id="canvasZone">
-            <canvas touch-action="none" id="renderCanvas"></canvas>
+        <div class="wrapper">
+            <div id="jsEditor"></div>
+            <div id="canvasZone">
+                <canvas touch-action="none" id="renderCanvas"></canvas>
+            </div>
         </div>
-    </div>
 
-    <span class="label" id="fpsLabel">FPS</span>
+        <span class="label" id="fpsLabel">FPS</span>
 
-    <div id="errorZone">
-    </div>
+        <div id="errorZone">
+        </div>
 
-    <div class="navbarBottom">
-        <div id="statusBar"></div>
-        <div class="links">
-            <div class='link'><a target='_new' href="https://www.netlify.com/">Deployed by Netlify</a></div>
-            <div class='link'> <a target='_new' href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a></div>
-            <div class='link'><a target='_new' href="https://www.babylonjs.com/sandbox">Sandbox</a></div>
-            <div class='link'><a target='_new' href="https://doc.babylonjs.com">Documentation</a></div>
-            <div class='link'><a target='_new' href="https://doc.babylonjs.com/playground">Search</a></div>
+        <div class="navbarBottom">
+            <div id="statusBar"></div>
+            <div class="links">
+                <div class='link'>
+                    <a target='_new' href="https://www.netlify.com/">Deployed by Netlify</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://www.babylonjs.com/sandbox">Sandbox</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://doc.babylonjs.com">Documentation</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://doc.babylonjs.com/playground">Search</a>
+                </div>
+            </div>
         </div>
-    </div>
 
-    <div id="saveLayer" class="save-layer">
-        <div class="save-form">
-            <label for="saveFormTitle">TITLE</label>
-            <div class="separator"></div>
-            <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
+        <div id="saveLayer" class="save-layer">
+            <div class="save-form">
+                <label for="saveFormTitle">TITLE</label>
+                <div class="separator"></div>
+                <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
 
-            <label for="saveFormDescription">DESCRIPTION</label>
-            <div class="separator"></div>
-            <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
+                <label for="saveFormDescription">DESCRIPTION</label>
+                <div class="separator"></div>
+                <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
 
-            <label for="saveFormTags">TAGS (separated by comma)</label>
-            <div class="separator"></div>
-            <textarea id="saveFormTags" rows="4" cols="10"></textarea>
+                <label for="saveFormTags">TAGS (separated by comma)</label>
+                <div class="separator"></div>
+                <textarea id="saveFormTags" rows="4" cols="10"></textarea>
 
-            <div class="save-form-buttons" id="saveFormButtons">
+                <div class="save-form-buttons" id="saveFormButtons">
 
-                <div id="saveFormButtonOk" class="button">OK</div>
-                <div id="saveFormButtonCancel" class="button">Cancel</div>
+                    <div id="saveFormButtonOk" class="button">OK</div>
+                    <div id="saveFormButtonCancel" class="button">Cancel</div>
+                </div>
             </div>
         </div>
-    </div>
 
-    <div id="waitDiv">
-        <span id="waitTitle">Babylon.js Playground<BR><BR><BR></span>
-        <img src="waitlogo.png" id="waitLogo"/>
-    </div>   
+        <div id="waitDiv">
+            <span id="waitTitle">Babylon.js Playground
+                <BR>
+                <BR>
+                <BR>
+            </span>
+            <img src="waitlogo.png" id="waitLogo" />
+        </div>
 
-    <script src="https://code.jquery.com/jquery.js"></script>
+        <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/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
+    }
+  }
+}

+ 6 - 0
Tools/Gulp/config.json

@@ -6,6 +6,12 @@
         "declarationFilename": "babylon.d.ts",
         "declarationModuleFilename": "babylon.module.d.ts",
         "outputDirectory": "../../dist/preview release",
+        "playgroundDirectory": "../../Playground/",
+        "intellisenseFile": "babylon.d.txt",
+        "intellisenseSources": [
+            "../../dist/preview release/babylon.d.ts",
+            "../../dist/preview release/gui/babylon.gui.d.ts"
+        ],
         "outputCustomConfigurationsDirectory": "../../dist/preview release/customConfigurations",
         "srcOutputDirectory": "../../src/",
         "currentConfig": "all"

+ 14 - 4
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
@@ -415,7 +412,8 @@ var buildExternalLibrary = function (library, settings, watch) {
 /**
  * The default task, concat and min the main BJS files.
  */
-gulp.task("default", ["typescript-all"], function () {
+gulp.task("default", function (cb) {
+    runSequence("typescript-all", "intellisense", cb);
 });
 
 gulp.task("mainBuild", function (cb) {
@@ -500,6 +498,18 @@ gulp.task("watch", [], function () {
     return tasks;
 });
 
+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));
+});
+
 /**
  * Embedded local dev env management.
  */

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


Разлика између датотеке није приказан због своје велике величине
+ 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>

+ 2 - 4
Viewer/dist/domExample.html

@@ -15,9 +15,8 @@
     </head>
 
     <body>
-        <babylon extends="minimal">
-            <model url="https://ugcorigin.s-microsoft.com/12/2e77b8e3-0000-0000-7a48-6505db2f0ef9/952/1508427934473.gltf" title="The Bus!"
-                subtitle="Remix3D" thumbnail="http://d33wubrfki0l68.cloudfront.net/7e08139ddee0ec38005f4232346c7f7386831300/fd934/githubuniverse/remix3d.png">
+        <babylon extends="minimal" scene.default-camera="false">
+            <model url="https://playground.babylonjs.com/scenes/BoomBox.glb" title="GLB Model" subtitle="BabylonJS">
             </model>
             <camera>
                 <behaviors>
@@ -27,7 +26,6 @@
             <lights>
                 <light1 type="1" shadow-enabled="true" position.y="0.5" direction.y="-1" intensity="4.5">
                     <shadow-config use-blur-exponential-shadow-map="true" use-kernel-blur="true" blur-kernel="64" blur-scale="4">
-
                     </shadow-config>
                 </light1>
             </lights>

Разлика између датотеке није приказан због своје велике величине
+ 5622 - 7086
Viewer/dist/viewer.js


Разлика између датотеке није приказан због своје велике величине
+ 38 - 0
Viewer/dist/viewer.min.js


+ 9 - 11
Viewer/package.json

@@ -23,7 +23,7 @@
     },
     "homepage": "https://github.com/BabylonJS/Babylon.js#readme",
     "devDependencies": {
-        "@types/node": "^8.0.51",
+        "@types/node": "^8.0.52",
         "base64-image-loader": "^1.2.0",
         "html-loader": "^0.5.1",
         "json-loader": "^0.5.7",
@@ -34,15 +34,13 @@
         "webpack-dev-server": "^2.9.4"
     },
     "dependencies": {
-        "babylonjs": "^3.1.0-beta1.1.1",
-        "babylonjs-loaders": "^3.1.0-beta1.1",
-        "babylonjs-materials": "^3.1.0-beta1.1",
-        "babylonjs-post-process": "^3.1.0-beta1.1",
-        "babylonjs-procedural-textures": "^3.1.0-beta1.1",
+        "babylonjs": "^3.1.0-beta3",
+        "babylonjs-loaders": "^3.1.0-beta3",
+        "babylonjs-materials": "^3.1.0-beta3",
+        "babylonjs-post-process": "^3.1.0-beta3",
+        "babylonjs-procedural-textures": "^3.1.0-beta3",
+        "deepmerge": "^2.0.1",
         "es6-promise": "^4.1.1",
-        "handlebars": "^4.0.11",
-        "lodash": "^4.17.4",
-        "lodash.merge": "^4.6.0",
-        "promise-polyfill": "^6.0.2"
+        "handlebars": "^4.0.11"
     }
-}
+}

+ 3 - 5
Viewer/src/configuration/configuration.ts

@@ -44,14 +44,12 @@ export interface ViewerConfiguration {
         scaling?: { x: number, y: number, z: number };
         parentObjectIndex?: number; // the index of the parent object of the model in the loaded meshes array.
 
-        [propName: string]: any; // further configuration, like title and creator
-    } | string,
-
-    description?: string | {
         title: string;
         subtitle?: string;
         thumbnail?: string; // URL or data-url
-    };
+
+        [propName: string]: any; // further configuration, like title and creator
+    } | string;
 
     scene?: {
         debug?: boolean;

+ 4 - 4
Viewer/src/configuration/loader.ts

@@ -2,7 +2,7 @@ import { mapperManager } from './mappers';
 import { ViewerConfiguration } from './configuration';
 import { getConfigurationType } from './types';
 
-import * as merge from 'lodash.merge';
+import deepmerge from 'deepmerge';
 
 export class ConfigurationLoader {
 
@@ -10,11 +10,11 @@ export class ConfigurationLoader {
 
     public loadConfiguration(initConfig: ViewerConfiguration = {}): Promise<ViewerConfiguration> {
 
-        let loadedConfig = merge({}, initConfig);
+        let loadedConfig = deepmerge({}, initConfig);
 
         let extendedConfiguration = getConfigurationType(loadedConfig && loadedConfig.extends);
 
-        loadedConfig = merge(extendedConfiguration, loadedConfig);
+        loadedConfig = deepmerge(extendedConfiguration, loadedConfig);
 
         if (loadedConfig.configuration) {
 
@@ -34,7 +34,7 @@ export class ConfigurationLoader {
             let mapper = mapperManager.getMapper(mapperType);
             return this.loadFile(url).then((data: any) => {
                 let parsed = mapper.map(data);
-                return merge(loadedConfig, parsed);
+                return deepmerge(loadedConfig, parsed);
             });
         } else {
             return Promise.resolve(loadedConfig);

+ 0 - 2
Viewer/src/configuration/mappers.ts

@@ -3,8 +3,6 @@ import { ViewerConfiguration } from './configuration';
 
 import { kebabToCamel } from '../helper';
 
-import * as merge from 'lodash.merge';
-
 export interface IMapper {
     map(rawSource: any): ViewerConfiguration;
 }

Разлика између датотеке није приказан због своје велике величине
+ 8 - 12
Viewer/src/configuration/types/default.ts


+ 3 - 1
Viewer/src/index.ts

@@ -1,3 +1,4 @@
+import { mapperManager } from './configuration/mappers';
 import { viewerManager } from './viewer/viewerManager';
 import { DefaultViewer } from './viewer/defaultViewer';
 import { AbstractViewer } from './viewer/viewer';
@@ -13,6 +14,7 @@ import { AbstractViewer } from './viewer/viewer';
 import 'babylonjs';
 import 'babylonjs-loaders';
 import 'babylonjs-materials';
+import '../assets/pep.min';
 
 import { InitTags } from './initializer';
 
@@ -27,4 +29,4 @@ setTimeout(() => {
 });
 
 // public API for initialization
-export { InitTags, DefaultViewer, AbstractViewer, viewerManager };
+export { InitTags, DefaultViewer, AbstractViewer, viewerManager, mapperManager };

+ 15 - 1
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 {
 
@@ -297,7 +311,7 @@ export function getTemplateAsHtml(templateConfig: ITemplateConfiguration): Promi
             return loadFile(location);
         } else {
             location = location.replace('#', '');
-            let element = document.getElementById('#' + location);
+            let element = document.getElementById(location);
             if (element) {
                 return Promise.resolve(element.innerHTML);
             } else {

+ 6 - 4
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);
                                 }
 
@@ -371,14 +371,16 @@ export class DefaultViewer extends AbstractViewer {
 
     private setupCamera(focusMeshes: Array<AbstractMesh> = []) {
 
+        let cameraConfig = this.configuration.camera || {};
         let sceneConfig = this.configuration.scene || { autoRotate: false, defaultCamera: true };
 
-        if (sceneConfig.defaultCamera) {
+        if (!this.configuration.camera && sceneConfig.defaultCamera) {
+            if (sceneConfig.autoRotate) {
+                this.camera.useAutoRotationBehavior = true;
+            }
             return;
         }
 
-        let cameraConfig = this.configuration.camera || {};
-
         if (cameraConfig.position) {
             this.camera.position.copyFromFloats(cameraConfig.position.x || 0, cameraConfig.position.y || 0, cameraConfig.position.z || 0);
         }

+ 4 - 0
Viewer/src/viewer/viewerManager.ts

@@ -32,6 +32,10 @@ class ViewerManager {
 
     public getViewerPromiseById(id: string): Promise<AbstractViewer> {
         return new Promise((resolve, reject) => {
+            let localViewer = this.getViewerById(id)
+            if (localViewer) {
+                return resolve(localViewer);
+            }
             let viewerFunction = (viewer: AbstractViewer) => {
                 if (viewer.getBaseId() === id) {
                     resolve(viewer);

+ 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
+                }
             }
         },
         {

Разлика између датотеке није приказан због своје велике величине
+ 11192 - 11158
dist/preview release/babylon.d.ts


Разлика између датотеке није приказан због своје велике величине
+ 52 - 0
dist/preview release/babylon.js


+ 250 - 166
dist/preview release/babylon.max.js

@@ -1767,17 +1767,27 @@ var BABYLON;
             return vector;
         };
         Vector3.Unproject = function (source, viewportWidth, viewportHeight, world, view, projection) {
+            var result = Vector3.Zero();
+            Vector3.UnprojectToRef(source, viewportWidth, viewportHeight, world, view, projection, result);
+            return result;
+        };
+        Vector3.UnprojectToRef = function (source, viewportWidth, viewportHeight, world, view, projection, result) {
+            Vector3.UnprojectFloatsToRef(source.x, source.y, source.z, viewportWidth, viewportHeight, world, view, projection, result);
+        };
+        Vector3.UnprojectFloatsToRef = function (sourceX, sourceY, sourceZ, viewportWidth, viewportHeight, world, view, projection, result) {
             var matrix = MathTmp.Matrix[0];
             world.multiplyToRef(view, matrix);
             matrix.multiplyToRef(projection, matrix);
             matrix.invert();
-            var screenSource = new Vector3(source.x / viewportWidth * 2 - 1, -(source.y / viewportHeight * 2 - 1), 2 * source.z - 1.0);
-            var vector = Vector3.TransformCoordinates(screenSource, matrix);
+            var screenSource = MathTmp.Vector3[0];
+            screenSource.x = sourceX / viewportWidth * 2 - 1;
+            screenSource.y = -(sourceY / viewportHeight * 2 - 1);
+            screenSource.z = 2 * sourceZ - 1.0;
+            Vector3.TransformCoordinatesToRef(screenSource, matrix, result);
             var num = screenSource.x * matrix.m[3] + screenSource.y * matrix.m[7] + screenSource.z * matrix.m[11] + matrix.m[15];
             if (BABYLON.Scalar.WithinEpsilon(num, 1.0)) {
-                vector = vector.scale(1.0 / num);
+                result.scaleInPlace(1.0 / num);
             }
-            return vector;
         };
         Vector3.Minimize = function (left, right) {
             var min = left.clone();
@@ -4443,7 +4453,7 @@ var BABYLON;
          * Returns the updated Path2.
          */
         Path2.prototype.addLineTo = function (x, y) {
-            if (closed) {
+            if (this.closed) {
                 //Tools.Error("cannot add lines to closed paths");
                 return this;
             }
@@ -4459,7 +4469,7 @@ var BABYLON;
          */
         Path2.prototype.addArcTo = function (midX, midY, endX, endY, numberOfSegments) {
             if (numberOfSegments === void 0) { numberOfSegments = 36; }
-            if (closed) {
+            if (this.closed) {
                 //Tools.Error("cannot add arcs to closed paths");
                 return this;
             }
@@ -5771,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)
@@ -6154,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);
@@ -6195,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;
         };
@@ -6374,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;
@@ -6405,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) {
@@ -6489,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
@@ -6532,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();
@@ -8512,7 +8539,7 @@ var BABYLON;
         });
         Object.defineProperty(Engine, "Version", {
             get: function () {
-                return "3.1-beta-3";
+                return "3.1-beta-5";
             },
             enumerable: true,
             configurable: true
@@ -14658,7 +14685,7 @@ var BABYLON;
             var min;
             var max;
             var boundingInfo = this.getBoundingInfo();
-            if (!this.subMeshes || !boundingInfo) {
+            if (!this.subMeshes) {
                 min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
                 max = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
             }
@@ -14673,7 +14700,7 @@ var BABYLON;
                     var childMesh = descendant;
                     childMesh.computeWorldMatrix(true);
                     var childBoundingInfo = childMesh.getBoundingInfo();
-                    if (childMesh.getTotalVertices() === 0 || !childBoundingInfo) {
+                    if (childMesh.getTotalVertices() === 0) {
                         continue;
                     }
                     var boundingBox = childBoundingInfo.boundingBox;
@@ -14852,10 +14879,8 @@ var BABYLON;
             this.computeWorldMatrix(true);
             var boundingInfo = this.getBoundingInfo();
             // Update octree
-            if (boundingInfo) {
-                var bbox = boundingInfo.boundingBox;
-                this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
-            }
+            var bbox = boundingInfo.boundingBox;
+            this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
             return this._submeshesOctree;
         };
         // Collisions
@@ -15178,9 +15203,12 @@ var BABYLON;
             var indices = this.getIndices();
             var normals = this.getVerticesData(BABYLON.VertexBuffer.NormalKind);
             var bInfo = this.getBoundingInfo();
+<<<<<<< HEAD
             if (!bInfo) {
                 return this;
             }
+=======
+>>>>>>> 67c83069a447868ab6def9019c048533b0046690
             if (this._facetDepthSort && !this._facetDepthSortEnabled) {
                 // init arrays, matrix and sort function on first call
                 this._facetDepthSortEnabled = true;
@@ -15333,9 +15361,6 @@ var BABYLON;
          */
         AbstractMesh.prototype.getFacetsAtLocalCoordinates = function (x, y, z) {
             var bInfo = this.getBoundingInfo();
-            if (!bInfo) {
-                return null;
-            }
             var ox = Math.floor((x - bInfo.minimum.x * this._partitioningBBoxRatio) * this._subDiv.X * this._partitioningBBoxRatio / this._bbSize.x);
             var oy = Math.floor((y - bInfo.minimum.y * this._partitioningBBoxRatio) * this._subDiv.Y * this._partitioningBBoxRatio / this._bbSize.y);
             var oz = Math.floor((z - bInfo.minimum.z * this._partitioningBBoxRatio) * this._subDiv.Z * this._partitioningBBoxRatio / this._bbSize.z);
@@ -17907,7 +17932,6 @@ var BABYLON;
              */
             this.onPointerObservable = new BABYLON.Observable();
             this._meshPickProceed = false;
-            this._previousHasSwiped = false;
             this._currentPickResult = null;
             this._previousPickResult = null;
             this._totalPointersPressed = 0;
@@ -18931,7 +18955,6 @@ var BABYLON;
                                     _this._previousStartingPointerPosition.x = _this._startingPointerPosition.x;
                                     _this._previousStartingPointerPosition.y = _this._startingPointerPosition.y;
                                     _this._previousButtonPressed = btn;
-                                    _this._previousHasSwiped = clickInfo.hasSwiped;
                                     if (Scene.ExclusiveDoubleClickMode) {
                                         if (_this._previousDelayedSimpleClickTimeout) {
                                             clearTimeout(_this._previousDelayedSimpleClickTimeout);
@@ -18950,7 +18973,6 @@ var BABYLON;
                                 _this._previousStartingPointerPosition.x = _this._startingPointerPosition.x;
                                 _this._previousStartingPointerPosition.y = _this._startingPointerPosition.y;
                                 _this._previousButtonPressed = btn;
-                                _this._previousHasSwiped = clickInfo.hasSwiped;
                             }
                         }
                     }
@@ -20103,9 +20125,7 @@ var BABYLON;
                 var material = subMesh.getMaterial();
                 if (mesh.showSubMeshesBoundingBox) {
                     var boundingInfo = subMesh.getBoundingInfo();
-                    if (boundingInfo) {
-                        this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
-                    }
+                    this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
                 }
                 if (material) {
                     // Render targets
@@ -20229,9 +20249,7 @@ var BABYLON;
             }
             if (sourceMesh.showBoundingBox || this.forceShowBoundingBoxes) {
                 var boundingInfo = sourceMesh.getBoundingInfo();
-                if (boundingInfo) {
-                    this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
-                }
+                this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
             }
             if (mesh && mesh.subMeshes) {
                 // Submeshes Octrees
@@ -20482,35 +20500,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
@@ -20972,12 +20992,10 @@ var BABYLON;
                 }
                 mesh.computeWorldMatrix(true);
                 var boundingInfo = mesh.getBoundingInfo();
-                if (boundingInfo) {
-                    var minBox = boundingInfo.boundingBox.minimumWorld;
-                    var maxBox = boundingInfo.boundingBox.maximumWorld;
-                    BABYLON.Tools.CheckExtends(minBox, min, max);
-                    BABYLON.Tools.CheckExtends(maxBox, min, max);
-                }
+                var minBox = boundingInfo.boundingBox.minimumWorld;
+                var maxBox = boundingInfo.boundingBox.maximumWorld;
+                BABYLON.Tools.CheckExtends(minBox, min, max);
+                BABYLON.Tools.CheckExtends(maxBox, min, max);
             }
             return {
                 min: min,
@@ -20998,6 +21016,12 @@ var BABYLON;
         // Picking
         Scene.prototype.createPickingRay = function (x, y, world, camera, cameraViewSpace) {
             if (cameraViewSpace === void 0) { cameraViewSpace = false; }
+            var result = BABYLON.Ray.Zero();
+            this.createPickingRayToRef(x, y, world, result, camera, cameraViewSpace);
+            return result;
+        };
+        Scene.prototype.createPickingRayToRef = function (x, y, world, result, camera, cameraViewSpace) {
+            if (cameraViewSpace === void 0) { cameraViewSpace = false; }
             var engine = this._engine;
             if (!camera) {
                 if (!this.activeCamera)
@@ -21009,12 +21033,17 @@ var BABYLON;
             // 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);
-            return BABYLON.Ray.CreateNew(x, y, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), cameraViewSpace ? BABYLON.Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
-            //       return BABYLON.Ray.CreateNew(x / window.devicePixelRatio, y / window.devicePixelRatio, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), camera.getViewMatrix(), camera.getProjectionMatrix());
+            result.update(x, y, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), cameraViewSpace ? BABYLON.Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
+            return this;
         };
         Scene.prototype.createPickingRayInCameraSpace = function (x, y, camera) {
+            var result = BABYLON.Ray.Zero();
+            this.createPickingRayInCameraSpaceToRef(x, y, result, camera);
+            return result;
+        };
+        Scene.prototype.createPickingRayInCameraSpaceToRef = function (x, y, result, camera) {
             if (!BABYLON.PickingInfo) {
-                return null;
+                return this;
             }
             var engine = this._engine;
             if (!camera) {
@@ -21028,7 +21057,8 @@ var BABYLON;
             // 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);
-            return BABYLON.Ray.CreateNew(x, y, viewport.width, viewport.height, identity, identity, camera.getProjectionMatrix());
+            result.update(x, y, viewport.width, viewport.height, identity, identity, camera.getProjectionMatrix());
+            return this;
         };
         Scene.prototype._internalPick = function (rayFunction, predicate, fastCheck) {
             if (!BABYLON.PickingInfo) {
@@ -21122,7 +21152,13 @@ var BABYLON;
          */
         Scene.prototype.pick = function (x, y, predicate, fastCheck, camera) {
             var _this = this;
-            return this._internalPick(function (world) { return _this.createPickingRay(x, y, world, camera || null); }, predicate, fastCheck);
+            if (!this._tempPickingRay) {
+                this._tempPickingRay = BABYLON.Ray.Zero();
+            }
+            return this._internalPick(function (world) {
+                _this.createPickingRayToRef(x, y, world, _this._tempPickingRay, camera || null);
+                return _this._tempPickingRay;
+            }, predicate, fastCheck);
         };
         /** Launch a ray to try to pick a sprite in the scene
          * @param x position on screen
@@ -21132,11 +21168,11 @@ var BABYLON;
          * @param camera camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used
          */
         Scene.prototype.pickSprite = function (x, y, predicate, fastCheck, camera) {
-            var ray = this.createPickingRayInCameraSpace(x, y, camera);
-            if (!ray) {
-                return null;
+            if (!this._tempPickingRay) {
+                this._tempPickingRay = BABYLON.Ray.Zero();
             }
-            return this._internalPickSprites(ray, predicate, fastCheck, camera);
+            this.createPickingRayInCameraSpaceToRef(x, y, this._tempPickingRay, camera);
+            return this._internalPickSprites(this._tempPickingRay, predicate, fastCheck, camera);
         };
         /** Use the given ray to pick a mesh in the scene
          * @param ray The ray to use to pick meshes
@@ -21151,7 +21187,7 @@ var BABYLON;
                 }
                 world.invertToRef(_this._pickWithRayInverseMatrix);
                 if (!_this._cachedRayForTransform) {
-                    _this._cachedRayForTransform = new BABYLON.Ray(BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero());
+                    _this._cachedRayForTransform = BABYLON.Ray.Zero();
                 }
                 BABYLON.Ray.TransformToRef(ray, _this._pickWithRayInverseMatrix, _this._cachedRayForTransform);
                 return _this._cachedRayForTransform;
@@ -21181,7 +21217,7 @@ var BABYLON;
                 }
                 world.invertToRef(_this._pickWithRayInverseMatrix);
                 if (!_this._cachedRayForTransform) {
-                    _this._cachedRayForTransform = new BABYLON.Ray(BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero());
+                    _this._cachedRayForTransform = BABYLON.Ray.Zero();
                 }
                 BABYLON.Ray.TransformToRef(ray, _this._pickWithRayInverseMatrix, _this._cachedRayForTransform);
                 return _this._cachedRayForTransform;
@@ -23217,9 +23253,6 @@ var BABYLON;
             }
             else {
                 var boundingInfo = this.getBoundingInfo();
-                if (!boundingInfo) {
-                    return this;
-                }
                 bSphere = boundingInfo.boundingSphere;
             }
             var distanceToCamera = bSphere.centerWorld.subtract(camera.globalPosition).length();
@@ -25687,9 +25720,6 @@ var BABYLON;
             var maxVector = null;
             meshes.forEach(function (mesh, index, array) {
                 var boundingInfo = mesh.getBoundingInfo();
-                if (!boundingInfo) {
-                    return;
-                }
                 var boundingBox = boundingInfo.boundingBox;
                 if (!minVector || !maxVector) {
                     minVector = boundingBox.minimumWorld;
@@ -25931,7 +25961,7 @@ var BABYLON;
             }
             var data = this._renderingMesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
             if (!data) {
-                this._boundingInfo = this._mesh._boundingInfo;
+                this._boundingInfo = this._mesh.getBoundingInfo();
                 return this;
             }
             var indices = this._renderingMesh.getIndices();
@@ -25939,9 +25969,6 @@ var BABYLON;
             //is this the only submesh?
             if (this.indexStart === 0 && this.indexCount === indices.length) {
                 var boundingInfo = this._renderingMesh.getBoundingInfo();
-                if (!boundingInfo) {
-                    return this;
-                }
                 //the rendering mesh's bounding info can be used, it is the standard submesh for all indices.
                 extend = { minimum: boundingInfo.minimum.clone(), maximum: boundingInfo.maximum.clone() };
             }
@@ -25953,9 +25980,6 @@ var BABYLON;
         };
         SubMesh.prototype._checkCollision = function (collider) {
             var boundingInfo = this._renderingMesh.getBoundingInfo();
-            if (!boundingInfo) {
-                return false;
-            }
             return boundingInfo._checkCollision(collider);
         };
         /**
@@ -29678,11 +29702,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);
@@ -29693,6 +29723,9 @@ var BABYLON;
             var vertexData = new VertexData();
             vertexData.indices = indices;
             vertexData.positions = positions;
+            if (colors) {
+                vertexData.colors = vertexColors;
+            }
             return vertexData;
         };
         /**
@@ -40430,9 +40463,6 @@ var BABYLON;
                         continue;
                     }
                     var boundingInfo = mesh.getBoundingInfo();
-                    if (!boundingInfo) {
-                        continue;
-                    }
                     var boundingBox = boundingInfo.boundingBox;
                     for (var index = 0; index < boundingBox.vectorsWorld.length; index++) {
                         BABYLON.Vector3.TransformCoordinatesToRef(boundingBox.vectorsWorld[index], viewMatrix, tempVector3);
@@ -44013,13 +44043,20 @@ var BABYLON;
             }
             return -1;
         };
+        Ray.prototype.update = function (x, y, viewportWidth, viewportHeight, world, view, projection) {
+            BABYLON.Vector3.UnprojectFloatsToRef(x, y, 0, viewportWidth, viewportHeight, world, view, projection, this.origin);
+            BABYLON.Vector3.UnprojectFloatsToRef(x, y, 1, viewportWidth, viewportHeight, world, view, projection, BABYLON.Tmp.Vector3[0]);
+            BABYLON.Tmp.Vector3[0].subtractToRef(this.origin, this.direction);
+            this.direction.normalize();
+            return this;
+        };
         // Statics
+        Ray.Zero = function () {
+            return new Ray(BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero());
+        };
         Ray.CreateNew = function (x, y, viewportWidth, viewportHeight, world, view, projection) {
-            var start = BABYLON.Vector3.Unproject(new BABYLON.Vector3(x, y, 0), viewportWidth, viewportHeight, world, view, projection);
-            var end = BABYLON.Vector3.Unproject(new BABYLON.Vector3(x, y, 1), viewportWidth, viewportHeight, world, view, projection);
-            var direction = end.subtract(start);
-            direction.normalize();
-            return new Ray(start, direction);
+            var result = Ray.Zero();
+            return result.update(x, y, viewportWidth, viewportHeight, world, view, projection);
         };
         /**
         * Function will create a new transformed ray starting from origin and ending at the end point. Ray's length will be set, and ray will be
@@ -46508,9 +46545,7 @@ var BABYLON;
             set: function (val) {
                 this._isVisibilityBoxLocked = val;
                 var boundingInfo = this.mesh.getBoundingInfo();
-                if (boundingInfo) {
-                    boundingInfo.isLocked = val;
-                }
+                boundingInfo.isLocked = val;
             },
             enumerable: true,
             configurable: true
@@ -47103,9 +47138,7 @@ var BABYLON;
          */
         InstancedMesh.prototype.refreshBoundingInfo = function () {
             var meshBB = this._sourceMesh.getBoundingInfo();
-            if (meshBB) {
-                this._boundingInfo = new BABYLON.BoundingInfo(meshBB.minimum.clone(), meshBB.maximum.clone());
-            }
+            this._boundingInfo = new BABYLON.BoundingInfo(meshBB.minimum.clone(), meshBB.maximum.clone());
             this._updateBoundingInfo();
             return this;
         };
@@ -47129,9 +47162,6 @@ var BABYLON;
                 return this;
             }
             var boundingInfo = this.getBoundingInfo();
-            if (!boundingInfo) {
-                return this;
-            }
             this._currentLOD = this.sourceMesh.getLOD(camera, boundingInfo.boundingSphere);
             if (this._currentLOD === this.sourceMesh) {
                 return this;
@@ -47202,27 +47232,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;
@@ -48156,6 +48194,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.
@@ -48163,24 +48203,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;
@@ -48192,12 +48250,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;
         };
         /**
@@ -49679,9 +49740,6 @@ var BABYLON;
         };
         Sound.prototype._onRegisterAfterWorldMatrixUpdate = function (connectedMesh) {
             var boundingInfo = connectedMesh.getBoundingInfo();
-            if (!boundingInfo) {
-                return;
-            }
             this.setPosition(boundingInfo.boundingSphere.centerWorld);
             if (BABYLON.Engine.audioEngine.canUseWebAudio && this._isDirectional && this.isPlaying) {
                 this._updateDirection();
@@ -52995,12 +53053,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:"
@@ -58185,8 +58243,8 @@ var BABYLON;
                 if (!material) {
                     return;
                 }
-                // Culling
-                engine.setState(material.backFaceCulling);
+                // Culling and reverse (right handed system)
+                engine.setState(material.backFaceCulling, 0, false, scene.useRightHandedSystem);
                 // Managing instances
                 var batch = mesh._getInstancesRenderList(subMesh._id);
                 if (batch.mustReturn) {
@@ -66640,13 +66698,7 @@ var BABYLON;
                 //calculate the world matrix with no rotation
                 this.object.computeWorldMatrix && this.object.computeWorldMatrix(true);
                 var boundingInfo = this.object.getBoundingInfo();
-                var size = void 0;
-                if (boundingInfo) {
-                    size = boundingInfo.boundingBox.extendSizeWorld.scale(2);
-                }
-                else {
-                    size = BABYLON.Vector3.Zero();
-                }
+                var size = boundingInfo.boundingBox.extendSizeWorld.scale(2);
                 //bring back the rotation
                 this.object.rotationQuaternion = q;
                 //calculate the world matrix with the new rotation
@@ -66660,9 +66712,6 @@ var BABYLON;
         PhysicsImpostor.prototype.getObjectCenter = function () {
             if (this.object.getBoundingInfo) {
                 var boundingInfo = this.object.getBoundingInfo();
-                if (!boundingInfo) {
-                    return this.object.position;
-                }
                 return boundingInfo.boundingBox.centerWorld;
             }
             else {
@@ -67444,7 +67493,7 @@ var BABYLON;
             //For now pointDepth will not be used and will be automatically calculated.
             //Future reference - try and find the best place to add a reference to the pointDepth variable.
             var arraySize = pointDepth || ~~(Math.sqrt(pos.length / 3) - 1);
-            var boundingInfo = (object.getBoundingInfo());
+            var boundingInfo = object.getBoundingInfo();
             var dim = Math.min(boundingInfo.boundingBox.extendSizeWorld.x, boundingInfo.boundingBox.extendSizeWorld.y);
             var minY = boundingInfo.boundingBox.extendSizeWorld.z;
             var elementSize = dim * 2 / arraySize;
@@ -69982,13 +70031,13 @@ var BABYLON;
         };
         Octree.CreationFuncForMeshes = function (entry, block) {
             var boundingInfo = entry.getBoundingInfo();
-            if (!entry.isBlocked && boundingInfo && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
+            if (!entry.isBlocked && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
                 block.entries.push(entry);
             }
         };
         Octree.CreationFuncForSubMeshes = function (entry, block) {
             var boundingInfo = entry.getBoundingInfo();
-            if (boundingInfo && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
+            if (boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
                 block.entries.push(entry);
             }
         };
@@ -75580,6 +75629,41 @@ var BABYLON;
             this.zoomOnBoundingInfo(boundingBox.minimumWorld, boundingBox.maximumWorld, focusOnOriginXZ, onAnimationEnd);
         };
         /**
+         * Targets the given mesh with its children and updates zoom level accordingly.
+         * @param mesh  The mesh to target.
+         * @param radius Optional. If a cached radius position already exists, overrides default.
+         * @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
+         * @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
+         * @param onAnimationEnd Callback triggered at the end of the framing animation
+         */
+        FramingBehavior.prototype.zoomOnMeshHierarchy = function (mesh, focusOnOriginXZ, onAnimationEnd) {
+            if (focusOnOriginXZ === void 0) { focusOnOriginXZ = false; }
+            if (onAnimationEnd === void 0) { onAnimationEnd = null; }
+            mesh.computeWorldMatrix(true);
+            var boundingBox = mesh.getHierarchyBoundingVectors(true);
+            this.zoomOnBoundingInfo(boundingBox.min, boundingBox.max, focusOnOriginXZ, onAnimationEnd);
+        };
+        /**
+         * Targets the given meshes with their children and updates zoom level accordingly.
+         * @param meshes  The mesh to target.
+         * @param radius Optional. If a cached radius position already exists, overrides default.
+         * @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
+         * @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
+         * @param onAnimationEnd Callback triggered at the end of the framing animation
+         */
+        FramingBehavior.prototype.zoomOnMeshesHierarchy = function (meshes, focusOnOriginXZ, onAnimationEnd) {
+            if (focusOnOriginXZ === void 0) { focusOnOriginXZ = false; }
+            if (onAnimationEnd === void 0) { onAnimationEnd = null; }
+            var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+            var max = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
+            for (var i = 0; i < meshes.length; i++) {
+                var boundingInfo = meshes[i].getHierarchyBoundingVectors(true);
+                BABYLON.Tools.CheckExtends(boundingInfo.min, min, max);
+                BABYLON.Tools.CheckExtends(boundingInfo.max, min, max);
+            }
+            this.zoomOnBoundingInfo(min, max, focusOnOriginXZ, onAnimationEnd);
+        };
+        /**
          * Targets the given mesh and updates zoom level accordingly.
          * @param mesh  The mesh to target.
          * @param radius Optional. If a cached radius position already exists, overrides default.

Разлика између датотеке није приказан због своје велике величине
+ 11192 - 11158
dist/preview release/babylon.module.d.ts


Разлика између датотеке није приказан због своје велике величине
+ 53 - 1
dist/preview release/babylon.worker.js


Разлика између датотеке није приказан због своје велике величине
+ 21636 - 11715
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


Разлика између датотеке није приказан због своје велике величине
+ 58 - 1
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


+ 271 - 167
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -1767,17 +1767,27 @@ var BABYLON;
             return vector;
         };
         Vector3.Unproject = function (source, viewportWidth, viewportHeight, world, view, projection) {
+            var result = Vector3.Zero();
+            Vector3.UnprojectToRef(source, viewportWidth, viewportHeight, world, view, projection, result);
+            return result;
+        };
+        Vector3.UnprojectToRef = function (source, viewportWidth, viewportHeight, world, view, projection, result) {
+            Vector3.UnprojectFloatsToRef(source.x, source.y, source.z, viewportWidth, viewportHeight, world, view, projection, result);
+        };
+        Vector3.UnprojectFloatsToRef = function (sourceX, sourceY, sourceZ, viewportWidth, viewportHeight, world, view, projection, result) {
             var matrix = MathTmp.Matrix[0];
             world.multiplyToRef(view, matrix);
             matrix.multiplyToRef(projection, matrix);
             matrix.invert();
-            var screenSource = new Vector3(source.x / viewportWidth * 2 - 1, -(source.y / viewportHeight * 2 - 1), 2 * source.z - 1.0);
-            var vector = Vector3.TransformCoordinates(screenSource, matrix);
+            var screenSource = MathTmp.Vector3[0];
+            screenSource.x = sourceX / viewportWidth * 2 - 1;
+            screenSource.y = -(sourceY / viewportHeight * 2 - 1);
+            screenSource.z = 2 * sourceZ - 1.0;
+            Vector3.TransformCoordinatesToRef(screenSource, matrix, result);
             var num = screenSource.x * matrix.m[3] + screenSource.y * matrix.m[7] + screenSource.z * matrix.m[11] + matrix.m[15];
             if (BABYLON.Scalar.WithinEpsilon(num, 1.0)) {
-                vector = vector.scale(1.0 / num);
+                result.scaleInPlace(1.0 / num);
             }
-            return vector;
         };
         Vector3.Minimize = function (left, right) {
             var min = left.clone();
@@ -4443,7 +4453,7 @@ var BABYLON;
          * Returns the updated Path2.
          */
         Path2.prototype.addLineTo = function (x, y) {
-            if (closed) {
+            if (this.closed) {
                 //Tools.Error("cannot add lines to closed paths");
                 return this;
             }
@@ -4459,7 +4469,7 @@ var BABYLON;
          */
         Path2.prototype.addArcTo = function (midX, midY, endX, endY, numberOfSegments) {
             if (numberOfSegments === void 0) { numberOfSegments = 36; }
-            if (closed) {
+            if (this.closed) {
                 //Tools.Error("cannot add arcs to closed paths");
                 return this;
             }
@@ -5771,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)
@@ -6154,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);
@@ -6195,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;
         };
@@ -6374,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;
@@ -6405,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) {
@@ -6489,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
@@ -6532,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();
@@ -8512,7 +8539,7 @@ var BABYLON;
         });
         Object.defineProperty(Engine, "Version", {
             get: function () {
-                return "3.1-beta-3";
+                return "3.1-beta-5";
             },
             enumerable: true,
             configurable: true
@@ -14658,7 +14685,7 @@ var BABYLON;
             var min;
             var max;
             var boundingInfo = this.getBoundingInfo();
-            if (!this.subMeshes || !boundingInfo) {
+            if (!this.subMeshes) {
                 min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
                 max = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
             }
@@ -14673,7 +14700,7 @@ var BABYLON;
                     var childMesh = descendant;
                     childMesh.computeWorldMatrix(true);
                     var childBoundingInfo = childMesh.getBoundingInfo();
-                    if (childMesh.getTotalVertices() === 0 || !childBoundingInfo) {
+                    if (childMesh.getTotalVertices() === 0) {
                         continue;
                     }
                     var boundingBox = childBoundingInfo.boundingBox;
@@ -14852,10 +14879,8 @@ var BABYLON;
             this.computeWorldMatrix(true);
             var boundingInfo = this.getBoundingInfo();
             // Update octree
-            if (boundingInfo) {
-                var bbox = boundingInfo.boundingBox;
-                this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
-            }
+            var bbox = boundingInfo.boundingBox;
+            this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
             return this._submeshesOctree;
         };
         // Collisions
@@ -15178,9 +15203,12 @@ var BABYLON;
             var indices = this.getIndices();
             var normals = this.getVerticesData(BABYLON.VertexBuffer.NormalKind);
             var bInfo = this.getBoundingInfo();
+<<<<<<< HEAD
             if (!bInfo) {
                 return this;
             }
+=======
+>>>>>>> 67c83069a447868ab6def9019c048533b0046690
             if (this._facetDepthSort && !this._facetDepthSortEnabled) {
                 // init arrays, matrix and sort function on first call
                 this._facetDepthSortEnabled = true;
@@ -15333,9 +15361,6 @@ var BABYLON;
          */
         AbstractMesh.prototype.getFacetsAtLocalCoordinates = function (x, y, z) {
             var bInfo = this.getBoundingInfo();
-            if (!bInfo) {
-                return null;
-            }
             var ox = Math.floor((x - bInfo.minimum.x * this._partitioningBBoxRatio) * this._subDiv.X * this._partitioningBBoxRatio / this._bbSize.x);
             var oy = Math.floor((y - bInfo.minimum.y * this._partitioningBBoxRatio) * this._subDiv.Y * this._partitioningBBoxRatio / this._bbSize.y);
             var oz = Math.floor((z - bInfo.minimum.z * this._partitioningBBoxRatio) * this._subDiv.Z * this._partitioningBBoxRatio / this._bbSize.z);
@@ -17907,7 +17932,6 @@ var BABYLON;
              */
             this.onPointerObservable = new BABYLON.Observable();
             this._meshPickProceed = false;
-            this._previousHasSwiped = false;
             this._currentPickResult = null;
             this._previousPickResult = null;
             this._totalPointersPressed = 0;
@@ -18931,7 +18955,6 @@ var BABYLON;
                                     _this._previousStartingPointerPosition.x = _this._startingPointerPosition.x;
                                     _this._previousStartingPointerPosition.y = _this._startingPointerPosition.y;
                                     _this._previousButtonPressed = btn;
-                                    _this._previousHasSwiped = clickInfo.hasSwiped;
                                     if (Scene.ExclusiveDoubleClickMode) {
                                         if (_this._previousDelayedSimpleClickTimeout) {
                                             clearTimeout(_this._previousDelayedSimpleClickTimeout);
@@ -18950,7 +18973,6 @@ var BABYLON;
                                 _this._previousStartingPointerPosition.x = _this._startingPointerPosition.x;
                                 _this._previousStartingPointerPosition.y = _this._startingPointerPosition.y;
                                 _this._previousButtonPressed = btn;
-                                _this._previousHasSwiped = clickInfo.hasSwiped;
                             }
                         }
                     }
@@ -20103,9 +20125,7 @@ var BABYLON;
                 var material = subMesh.getMaterial();
                 if (mesh.showSubMeshesBoundingBox) {
                     var boundingInfo = subMesh.getBoundingInfo();
-                    if (boundingInfo) {
-                        this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
-                    }
+                    this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
                 }
                 if (material) {
                     // Render targets
@@ -20229,9 +20249,7 @@ var BABYLON;
             }
             if (sourceMesh.showBoundingBox || this.forceShowBoundingBoxes) {
                 var boundingInfo = sourceMesh.getBoundingInfo();
-                if (boundingInfo) {
-                    this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
-                }
+                this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
             }
             if (mesh && mesh.subMeshes) {
                 // Submeshes Octrees
@@ -20482,35 +20500,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
@@ -20972,12 +20992,10 @@ var BABYLON;
                 }
                 mesh.computeWorldMatrix(true);
                 var boundingInfo = mesh.getBoundingInfo();
-                if (boundingInfo) {
-                    var minBox = boundingInfo.boundingBox.minimumWorld;
-                    var maxBox = boundingInfo.boundingBox.maximumWorld;
-                    BABYLON.Tools.CheckExtends(minBox, min, max);
-                    BABYLON.Tools.CheckExtends(maxBox, min, max);
-                }
+                var minBox = boundingInfo.boundingBox.minimumWorld;
+                var maxBox = boundingInfo.boundingBox.maximumWorld;
+                BABYLON.Tools.CheckExtends(minBox, min, max);
+                BABYLON.Tools.CheckExtends(maxBox, min, max);
             }
             return {
                 min: min,
@@ -20998,6 +21016,12 @@ var BABYLON;
         // Picking
         Scene.prototype.createPickingRay = function (x, y, world, camera, cameraViewSpace) {
             if (cameraViewSpace === void 0) { cameraViewSpace = false; }
+            var result = BABYLON.Ray.Zero();
+            this.createPickingRayToRef(x, y, world, result, camera, cameraViewSpace);
+            return result;
+        };
+        Scene.prototype.createPickingRayToRef = function (x, y, world, result, camera, cameraViewSpace) {
+            if (cameraViewSpace === void 0) { cameraViewSpace = false; }
             var engine = this._engine;
             if (!camera) {
                 if (!this.activeCamera)
@@ -21009,12 +21033,17 @@ var BABYLON;
             // 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);
-            return BABYLON.Ray.CreateNew(x, y, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), cameraViewSpace ? BABYLON.Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
-            //       return BABYLON.Ray.CreateNew(x / window.devicePixelRatio, y / window.devicePixelRatio, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), camera.getViewMatrix(), camera.getProjectionMatrix());
+            result.update(x, y, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), cameraViewSpace ? BABYLON.Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
+            return this;
         };
         Scene.prototype.createPickingRayInCameraSpace = function (x, y, camera) {
+            var result = BABYLON.Ray.Zero();
+            this.createPickingRayInCameraSpaceToRef(x, y, result, camera);
+            return result;
+        };
+        Scene.prototype.createPickingRayInCameraSpaceToRef = function (x, y, result, camera) {
             if (!BABYLON.PickingInfo) {
-                return null;
+                return this;
             }
             var engine = this._engine;
             if (!camera) {
@@ -21028,7 +21057,8 @@ var BABYLON;
             // 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);
-            return BABYLON.Ray.CreateNew(x, y, viewport.width, viewport.height, identity, identity, camera.getProjectionMatrix());
+            result.update(x, y, viewport.width, viewport.height, identity, identity, camera.getProjectionMatrix());
+            return this;
         };
         Scene.prototype._internalPick = function (rayFunction, predicate, fastCheck) {
             if (!BABYLON.PickingInfo) {
@@ -21122,7 +21152,13 @@ var BABYLON;
          */
         Scene.prototype.pick = function (x, y, predicate, fastCheck, camera) {
             var _this = this;
-            return this._internalPick(function (world) { return _this.createPickingRay(x, y, world, camera || null); }, predicate, fastCheck);
+            if (!this._tempPickingRay) {
+                this._tempPickingRay = BABYLON.Ray.Zero();
+            }
+            return this._internalPick(function (world) {
+                _this.createPickingRayToRef(x, y, world, _this._tempPickingRay, camera || null);
+                return _this._tempPickingRay;
+            }, predicate, fastCheck);
         };
         /** Launch a ray to try to pick a sprite in the scene
          * @param x position on screen
@@ -21132,11 +21168,11 @@ var BABYLON;
          * @param camera camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used
          */
         Scene.prototype.pickSprite = function (x, y, predicate, fastCheck, camera) {
-            var ray = this.createPickingRayInCameraSpace(x, y, camera);
-            if (!ray) {
-                return null;
+            if (!this._tempPickingRay) {
+                this._tempPickingRay = BABYLON.Ray.Zero();
             }
-            return this._internalPickSprites(ray, predicate, fastCheck, camera);
+            this.createPickingRayInCameraSpaceToRef(x, y, this._tempPickingRay, camera);
+            return this._internalPickSprites(this._tempPickingRay, predicate, fastCheck, camera);
         };
         /** Use the given ray to pick a mesh in the scene
          * @param ray The ray to use to pick meshes
@@ -21151,7 +21187,7 @@ var BABYLON;
                 }
                 world.invertToRef(_this._pickWithRayInverseMatrix);
                 if (!_this._cachedRayForTransform) {
-                    _this._cachedRayForTransform = new BABYLON.Ray(BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero());
+                    _this._cachedRayForTransform = BABYLON.Ray.Zero();
                 }
                 BABYLON.Ray.TransformToRef(ray, _this._pickWithRayInverseMatrix, _this._cachedRayForTransform);
                 return _this._cachedRayForTransform;
@@ -21181,7 +21217,7 @@ var BABYLON;
                 }
                 world.invertToRef(_this._pickWithRayInverseMatrix);
                 if (!_this._cachedRayForTransform) {
-                    _this._cachedRayForTransform = new BABYLON.Ray(BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero());
+                    _this._cachedRayForTransform = BABYLON.Ray.Zero();
                 }
                 BABYLON.Ray.TransformToRef(ray, _this._pickWithRayInverseMatrix, _this._cachedRayForTransform);
                 return _this._cachedRayForTransform;
@@ -23217,9 +23253,6 @@ var BABYLON;
             }
             else {
                 var boundingInfo = this.getBoundingInfo();
-                if (!boundingInfo) {
-                    return this;
-                }
                 bSphere = boundingInfo.boundingSphere;
             }
             var distanceToCamera = bSphere.centerWorld.subtract(camera.globalPosition).length();
@@ -25687,9 +25720,6 @@ var BABYLON;
             var maxVector = null;
             meshes.forEach(function (mesh, index, array) {
                 var boundingInfo = mesh.getBoundingInfo();
-                if (!boundingInfo) {
-                    return;
-                }
                 var boundingBox = boundingInfo.boundingBox;
                 if (!minVector || !maxVector) {
                     minVector = boundingBox.minimumWorld;
@@ -25931,7 +25961,7 @@ var BABYLON;
             }
             var data = this._renderingMesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
             if (!data) {
-                this._boundingInfo = this._mesh._boundingInfo;
+                this._boundingInfo = this._mesh.getBoundingInfo();
                 return this;
             }
             var indices = this._renderingMesh.getIndices();
@@ -25939,9 +25969,6 @@ var BABYLON;
             //is this the only submesh?
             if (this.indexStart === 0 && this.indexCount === indices.length) {
                 var boundingInfo = this._renderingMesh.getBoundingInfo();
-                if (!boundingInfo) {
-                    return this;
-                }
                 //the rendering mesh's bounding info can be used, it is the standard submesh for all indices.
                 extend = { minimum: boundingInfo.minimum.clone(), maximum: boundingInfo.maximum.clone() };
             }
@@ -25953,9 +25980,6 @@ var BABYLON;
         };
         SubMesh.prototype._checkCollision = function (collider) {
             var boundingInfo = this._renderingMesh.getBoundingInfo();
-            if (!boundingInfo) {
-                return false;
-            }
             return boundingInfo._checkCollision(collider);
         };
         /**
@@ -29678,11 +29702,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);
@@ -29693,6 +29723,9 @@ var BABYLON;
             var vertexData = new VertexData();
             vertexData.indices = indices;
             vertexData.positions = positions;
+            if (colors) {
+                vertexData.colors = vertexColors;
+            }
             return vertexData;
         };
         /**
@@ -40430,9 +40463,6 @@ var BABYLON;
                         continue;
                     }
                     var boundingInfo = mesh.getBoundingInfo();
-                    if (!boundingInfo) {
-                        continue;
-                    }
                     var boundingBox = boundingInfo.boundingBox;
                     for (var index = 0; index < boundingBox.vectorsWorld.length; index++) {
                         BABYLON.Vector3.TransformCoordinatesToRef(boundingBox.vectorsWorld[index], viewMatrix, tempVector3);
@@ -44013,13 +44043,20 @@ var BABYLON;
             }
             return -1;
         };
+        Ray.prototype.update = function (x, y, viewportWidth, viewportHeight, world, view, projection) {
+            BABYLON.Vector3.UnprojectFloatsToRef(x, y, 0, viewportWidth, viewportHeight, world, view, projection, this.origin);
+            BABYLON.Vector3.UnprojectFloatsToRef(x, y, 1, viewportWidth, viewportHeight, world, view, projection, BABYLON.Tmp.Vector3[0]);
+            BABYLON.Tmp.Vector3[0].subtractToRef(this.origin, this.direction);
+            this.direction.normalize();
+            return this;
+        };
         // Statics
+        Ray.Zero = function () {
+            return new Ray(BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero());
+        };
         Ray.CreateNew = function (x, y, viewportWidth, viewportHeight, world, view, projection) {
-            var start = BABYLON.Vector3.Unproject(new BABYLON.Vector3(x, y, 0), viewportWidth, viewportHeight, world, view, projection);
-            var end = BABYLON.Vector3.Unproject(new BABYLON.Vector3(x, y, 1), viewportWidth, viewportHeight, world, view, projection);
-            var direction = end.subtract(start);
-            direction.normalize();
-            return new Ray(start, direction);
+            var result = Ray.Zero();
+            return result.update(x, y, viewportWidth, viewportHeight, world, view, projection);
         };
         /**
         * Function will create a new transformed ray starting from origin and ending at the end point. Ray's length will be set, and ray will be
@@ -46354,9 +46391,7 @@ var BABYLON;
             set: function (val) {
                 this._isVisibilityBoxLocked = val;
                 var boundingInfo = this.mesh.getBoundingInfo();
-                if (boundingInfo) {
-                    boundingInfo.isLocked = val;
-                }
+                boundingInfo.isLocked = val;
             },
             enumerable: true,
             configurable: true
@@ -46949,9 +46984,7 @@ var BABYLON;
          */
         InstancedMesh.prototype.refreshBoundingInfo = function () {
             var meshBB = this._sourceMesh.getBoundingInfo();
-            if (meshBB) {
-                this._boundingInfo = new BABYLON.BoundingInfo(meshBB.minimum.clone(), meshBB.maximum.clone());
-            }
+            this._boundingInfo = new BABYLON.BoundingInfo(meshBB.minimum.clone(), meshBB.maximum.clone());
             this._updateBoundingInfo();
             return this;
         };
@@ -46975,9 +47008,6 @@ var BABYLON;
                 return this;
             }
             var boundingInfo = this.getBoundingInfo();
-            if (!boundingInfo) {
-                return this;
-            }
             this._currentLOD = this.sourceMesh.getLOD(camera, boundingInfo.boundingSphere);
             if (this._currentLOD === this.sourceMesh) {
                 return this;
@@ -47048,27 +47078,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;
@@ -48002,6 +48040,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.
@@ -48009,24 +48049,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;
@@ -48038,12 +48096,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;
         };
         /**
@@ -49525,9 +49586,6 @@ var BABYLON;
         };
         Sound.prototype._onRegisterAfterWorldMatrixUpdate = function (connectedMesh) {
             var boundingInfo = connectedMesh.getBoundingInfo();
-            if (!boundingInfo) {
-                return;
-            }
             this.setPosition(boundingInfo.boundingSphere.centerWorld);
             if (BABYLON.Engine.audioEngine.canUseWebAudio && this._isDirectional && this.isPlaying) {
                 this._updateDirection();
@@ -52841,12 +52899,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:"
@@ -58031,8 +58089,8 @@ var BABYLON;
                 if (!material) {
                     return;
                 }
-                // Culling
-                engine.setState(material.backFaceCulling);
+                // Culling and reverse (right handed system)
+                engine.setState(material.backFaceCulling, 0, false, scene.useRightHandedSystem);
                 // Managing instances
                 var batch = mesh._getInstancesRenderList(subMesh._id);
                 if (batch.mustReturn) {
@@ -66486,13 +66544,7 @@ var BABYLON;
                 //calculate the world matrix with no rotation
                 this.object.computeWorldMatrix && this.object.computeWorldMatrix(true);
                 var boundingInfo = this.object.getBoundingInfo();
-                var size = void 0;
-                if (boundingInfo) {
-                    size = boundingInfo.boundingBox.extendSizeWorld.scale(2);
-                }
-                else {
-                    size = BABYLON.Vector3.Zero();
-                }
+                var size = boundingInfo.boundingBox.extendSizeWorld.scale(2);
                 //bring back the rotation
                 this.object.rotationQuaternion = q;
                 //calculate the world matrix with the new rotation
@@ -66506,9 +66558,6 @@ var BABYLON;
         PhysicsImpostor.prototype.getObjectCenter = function () {
             if (this.object.getBoundingInfo) {
                 var boundingInfo = this.object.getBoundingInfo();
-                if (!boundingInfo) {
-                    return this.object.position;
-                }
                 return boundingInfo.boundingBox.centerWorld;
             }
             else {
@@ -67290,7 +67339,7 @@ var BABYLON;
             //For now pointDepth will not be used and will be automatically calculated.
             //Future reference - try and find the best place to add a reference to the pointDepth variable.
             var arraySize = pointDepth || ~~(Math.sqrt(pos.length / 3) - 1);
-            var boundingInfo = (object.getBoundingInfo());
+            var boundingInfo = object.getBoundingInfo();
             var dim = Math.min(boundingInfo.boundingBox.extendSizeWorld.x, boundingInfo.boundingBox.extendSizeWorld.y);
             var minY = boundingInfo.boundingBox.extendSizeWorld.z;
             var elementSize = dim * 2 / arraySize;
@@ -69828,13 +69877,13 @@ var BABYLON;
         };
         Octree.CreationFuncForMeshes = function (entry, block) {
             var boundingInfo = entry.getBoundingInfo();
-            if (!entry.isBlocked && boundingInfo && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
+            if (!entry.isBlocked && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
                 block.entries.push(entry);
             }
         };
         Octree.CreationFuncForSubMeshes = function (entry, block) {
             var boundingInfo = entry.getBoundingInfo();
-            if (boundingInfo && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
+            if (boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
                 block.entries.push(entry);
             }
         };
@@ -75426,6 +75475,41 @@ var BABYLON;
             this.zoomOnBoundingInfo(boundingBox.minimumWorld, boundingBox.maximumWorld, focusOnOriginXZ, onAnimationEnd);
         };
         /**
+         * Targets the given mesh with its children and updates zoom level accordingly.
+         * @param mesh  The mesh to target.
+         * @param radius Optional. If a cached radius position already exists, overrides default.
+         * @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
+         * @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
+         * @param onAnimationEnd Callback triggered at the end of the framing animation
+         */
+        FramingBehavior.prototype.zoomOnMeshHierarchy = function (mesh, focusOnOriginXZ, onAnimationEnd) {
+            if (focusOnOriginXZ === void 0) { focusOnOriginXZ = false; }
+            if (onAnimationEnd === void 0) { onAnimationEnd = null; }
+            mesh.computeWorldMatrix(true);
+            var boundingBox = mesh.getHierarchyBoundingVectors(true);
+            this.zoomOnBoundingInfo(boundingBox.min, boundingBox.max, focusOnOriginXZ, onAnimationEnd);
+        };
+        /**
+         * Targets the given meshes with their children and updates zoom level accordingly.
+         * @param meshes  The mesh to target.
+         * @param radius Optional. If a cached radius position already exists, overrides default.
+         * @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
+         * @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
+         * @param onAnimationEnd Callback triggered at the end of the framing animation
+         */
+        FramingBehavior.prototype.zoomOnMeshesHierarchy = function (meshes, focusOnOriginXZ, onAnimationEnd) {
+            if (focusOnOriginXZ === void 0) { focusOnOriginXZ = false; }
+            if (onAnimationEnd === void 0) { onAnimationEnd = null; }
+            var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+            var max = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
+            for (var i = 0; i < meshes.length; i++) {
+                var boundingInfo = meshes[i].getHierarchyBoundingVectors(true);
+                BABYLON.Tools.CheckExtends(boundingInfo.min, min, max);
+                BABYLON.Tools.CheckExtends(boundingInfo.max, min, max);
+            }
+            this.zoomOnBoundingInfo(min, max, focusOnOriginXZ, onAnimationEnd);
+        };
+        /**
          * Targets the given mesh and updates zoom level accordingly.
          * @param mesh  The mesh to target.
          * @param radius Optional. If a cached radius position already exists, overrides default.
@@ -80737,6 +80821,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]) {
@@ -80747,6 +80839,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;
@@ -80807,7 +80907,11 @@ var BABYLON;
                     loaded += request._loaded;
                     total += request._total;
                 }
+<<<<<<< HEAD
                 this._progressCallback(new ProgressEvent("GLTFLoaderProgress", {
+=======
+                this._progressCallback(GLTFLoader._progressEventFactory("GLTFLoaderProgress", {
+>>>>>>> 67c83069a447868ab6def9019c048533b0046690
                     lengthComputable: true,
                     loaded: loaded,
                     total: total

Разлика између датотеке није приказан због своје велике величине
+ 20458 - 10689
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


+ 8 - 2
dist/preview release/gui/babylon.gui.js

@@ -212,6 +212,9 @@ var BABYLON;
                 if (this._pointerObserver) {
                     scene.onPointerObservable.remove(this._pointerObserver);
                 }
+                if (this._preKeyboardObserver) {
+                    scene.onPreKeyboardObservable.remove(this._preKeyboardObserver);
+                }
                 if (this._canvasPointerOutObserver) {
                     scene.getEngine().onCanvasPointerOutObservable.remove(this._canvasPointerOutObserver);
                 }
@@ -459,7 +462,7 @@ var BABYLON;
             AdvancedDynamicTexture.CreateFullscreenUI = function (name, foreground, scene) {
                 if (foreground === void 0) { foreground = true; }
                 if (scene === void 0) { scene = null; }
-                var result = new AdvancedDynamicTexture(name, 0, 0, scene);
+                var result = new AdvancedDynamicTexture(name, 0, 0, scene, false, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
                 // Display
                 var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
                 layer.texture = result;
@@ -1990,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)) {
@@ -2003,6 +2006,9 @@ var BABYLON;
                         return true;
                     }
                 }
+                if (!this.isHitTestVisible) {
+                    return false;
+                }
                 return this._processObservables(type, x, y, buttonIndex);
             };
             Container.prototype._clipForChildren = function (context) {

Разлика између датотеке није приказан због своје велике величине
+ 3 - 3
dist/preview release/gui/babylon.gui.min.js


Разлика између датотеке није приказан због своје велике величине
+ 267 - 260
dist/preview release/inspector/babylon.inspector.bundle.js


+ 11 - 0
dist/preview release/inspector/babylon.inspector.d.ts

@@ -182,6 +182,17 @@ declare module INSPECTOR {
         };
         'Scene': {
             type: typeof BABYLON.Scene;
+<<<<<<< HEAD
+=======
+        };
+        'TransformNode': {
+            type: typeof BABYLON.TransformNode;
+            format: (m: BABYLON.TransformNode) => string;
+        };
+        'AbstractMesh': {
+            type: typeof BABYLON.AbstractMesh;
+            format: (m: BABYLON.AbstractMesh) => string;
+>>>>>>> 67c83069a447868ab6def9019c048533b0046690
         };
         'Mesh': {
             type: typeof BABYLON.Mesh;

+ 12 - 1
dist/preview release/inspector/babylon.inspector.js

@@ -440,6 +440,17 @@ var INSPECTOR;
         },
         'Scene': {
             type: BABYLON.Scene,
+<<<<<<< HEAD
+=======
+        },
+        'TransformNode': {
+            type: BABYLON.TransformNode,
+            format: function (m) { return m.name; }
+        },
+        'AbstractMesh': {
+            type: BABYLON.AbstractMesh,
+            format: function (m) { return m.name; }
+>>>>>>> 67c83069a447868ab6def9019c048533b0046690
         },
         'Mesh': {
             type: BABYLON.Mesh,
@@ -1065,7 +1076,7 @@ var INSPECTOR;
             this._obj.isVisible = b;
         };
         MeshAdapter.prototype.isVisible = function () {
-            return this._obj.isEnabled() && this._obj.isVisible;
+            return this._obj.isEnabled() && (this._obj.isVisible === undefined || this._obj.isVisible);
         };
         MeshAdapter.prototype.isBoxVisible = function () {
             return this._obj.showBoundingBox;

Разлика између датотеке није приказан због своје велике величине
+ 8 - 1
dist/preview release/inspector/babylon.inspector.min.js


Разлика између датотеке није приказан због своје велике величине
+ 6 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 3 - 0
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -324,6 +324,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;

+ 31 - 0
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -333,6 +333,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]) {
@@ -343,6 +351,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;
@@ -392,6 +408,7 @@ var BABYLON;
             GLTFLoader.prototype._onProgress = function () {
                 if (!this._progressCallback) {
                     return;
+<<<<<<< HEAD
                 }
                 var loaded = 0;
                 var total = 0;
@@ -404,6 +421,20 @@ var BABYLON;
                     total += request._total;
                 }
                 this._progressCallback(new ProgressEvent("GLTFLoaderProgress", {
+=======
+                }
+                var loaded = 0;
+                var total = 0;
+                for (var _i = 0, _a = this._requests; _i < _a.length; _i++) {
+                    var request = _a[_i];
+                    if (!request._loaded || !request._total) {
+                        return;
+                    }
+                    loaded += request._loaded;
+                    total += request._total;
+                }
+                this._progressCallback(GLTFLoader._progressEventFactory("GLTFLoaderProgress", {
+>>>>>>> 67c83069a447868ab6def9019c048533b0046690
                     lengthComputable: true,
                     loaded: loaded,
                     total: total

Разлика између датотеке није приказан због своје велике величине
+ 6 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 3 - 0
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -871,6 +871,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;

+ 31 - 0
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -2478,6 +2478,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]) {
@@ -2488,6 +2496,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;
@@ -2537,6 +2553,7 @@ var BABYLON;
             GLTFLoader.prototype._onProgress = function () {
                 if (!this._progressCallback) {
                     return;
+<<<<<<< HEAD
                 }
                 var loaded = 0;
                 var total = 0;
@@ -2549,6 +2566,20 @@ var BABYLON;
                     total += request._total;
                 }
                 this._progressCallback(new ProgressEvent("GLTFLoaderProgress", {
+=======
+                }
+                var loaded = 0;
+                var total = 0;
+                for (var _i = 0, _a = this._requests; _i < _a.length; _i++) {
+                    var request = _a[_i];
+                    if (!request._loaded || !request._total) {
+                        return;
+                    }
+                    loaded += request._loaded;
+                    total += request._total;
+                }
+                this._progressCallback(GLTFLoader._progressEventFactory("GLTFLoaderProgress", {
+>>>>>>> 67c83069a447868ab6def9019c048533b0046690
                     lengthComputable: true,
                     loaded: loaded,
                     total: total

Разлика између датотеке није приказан због своје велике величине
+ 7 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 31 - 0
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;
@@ -3493,6 +3509,7 @@ var BABYLON;
             GLTFLoader.prototype._onProgress = function () {
                 if (!this._progressCallback) {
                     return;
+<<<<<<< HEAD
                 }
                 var loaded = 0;
                 var total = 0;
@@ -3505,6 +3522,20 @@ var BABYLON;
                     total += request._total;
                 }
                 this._progressCallback(new ProgressEvent("GLTFLoaderProgress", {
+=======
+                }
+                var loaded = 0;
+                var total = 0;
+                for (var _i = 0, _a = this._requests; _i < _a.length; _i++) {
+                    var request = _a[_i];
+                    if (!request._loaded || !request._total) {
+                        return;
+                    }
+                    loaded += request._loaded;
+                    total += request._total;
+                }
+                this._progressCallback(GLTFLoader._progressEventFactory("GLTFLoaderProgress", {
+>>>>>>> 67c83069a447868ab6def9019c048533b0046690
                     lengthComputable: true,
                     loaded: loaded,
                     total: total

Разлика између датотеке није приказан због своје велике величине
+ 7 - 1
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;

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


Разлика између датотеке није приказан због своје велике величине
+ 3 - 3
dist/preview release/materialsLibrary/babylonjs.materials.min.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


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

@@ -1,6 +1,8 @@
 # 3.1.0:
 
 ## Major updates
+- Viewer (TODO)
+- EnvironmentHelper + BackgroundMaterial (TODO)
 - Added support for webgl context lost and restored events. [Doc here](http://doc.babylonjs.com/tutorials/optimizing_your_scene#handling-webgl-context-lost) ([deltakosh](https://github.com/deltakosh))
 - Added support for non-pow2 textures when in WebGL2 mode ([deltakosh](https://github.com/deltakosh))
 - Engine can now be initialized with an existing webgl context ([deltakosh](https://github.com/deltakosh))
@@ -47,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))

+ 6 - 2
gui/src/advancedDynamicTexture.ts

@@ -215,6 +215,10 @@ module BABYLON.GUI {
                 scene.onPointerObservable.remove(this._pointerObserver);
             }
 
+            if (this._preKeyboardObserver) {
+                scene.onPreKeyboardObservable.remove(this._preKeyboardObserver);
+            }
+
             if (this._canvasPointerOutObserver) {
                 scene.getEngine().onCanvasPointerOutObservable.remove(this._canvasPointerOutObserver);
             }
@@ -300,7 +304,7 @@ module BABYLON.GUI {
                         continue;
                     }
                     
-                    var position = (<BoundingInfo>mesh.getBoundingInfo()).boundingSphere.center;
+                    var position = mesh.getBoundingInfo().boundingSphere.center;
                     var projectedPosition = Vector3.Project(position, mesh.getWorldMatrix(), scene.getTransformMatrix(), globalViewport);
 
                     if (projectedPosition.z < 0 || projectedPosition.z > 1) {
@@ -509,7 +513,7 @@ module BABYLON.GUI {
         }
 
         public static CreateFullscreenUI(name: string, foreground: boolean = true, scene: Nullable<Scene> = null): AdvancedDynamicTexture {
-            var result = new AdvancedDynamicTexture(name, 0, 0, scene);
+            var result = new AdvancedDynamicTexture(name, 0, 0, scene, false, Texture.BILINEAR_SAMPLINGMODE);
 
             // Display
             var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);

+ 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);
         }
 

+ 2 - 2
inspector/src/adapters/MeshAdapter.ts

@@ -51,7 +51,7 @@ module INSPECTOR {
             this._obj.isVisible = b;
         }
         public isVisible(): boolean {
-            return this._obj.isEnabled() && this._obj.isVisible;
+            return this._obj.isEnabled() && (this._obj.isVisible === undefined || this._obj.isVisible);
         }
         public isBoxVisible(): boolean {
             return (this._obj as BABYLON.AbstractMesh).showBoundingBox;
@@ -100,7 +100,7 @@ module INSPECTOR {
                 let matrix = mesh.getWorldMatrix();
                 let extend = new BABYLON.Vector3(1, 1, 1);
                 if (mesh instanceof BABYLON.AbstractMesh) {
-                    extend = mesh.getBoundingInfo()!.boundingBox.extendSizeWorld;
+                    extend = mesh.getBoundingInfo().boundingBox.extendSizeWorld;
                 }
                 this._axesViewer!.scaleLines = Math.max(extend.x, extend.y, extend.z) * 2;
                 this._axesViewer!.update(this._obj.position, BABYLON.Vector3.TransformNormal(x, matrix), BABYLON.Vector3.TransformNormal(y, matrix), BABYLON.Vector3.TransformNormal(z, matrix));

+ 8 - 0
inspector/src/properties.ts

@@ -90,6 +90,14 @@ module INSPECTOR {
         'Scene': {
             type: BABYLON.Scene,
         },
+        'TransformNode': {
+            type: BABYLON.TransformNode,
+            format: (m: BABYLON.TransformNode): string => { return m.name; }
+        },        
+        'AbstractMesh': {
+            type: BABYLON.AbstractMesh,
+            format: (m: BABYLON.AbstractMesh): string => { return m.name; }
+        },          
         'Mesh': {
             type: BABYLON.Mesh,
             format: (m: BABYLON.Mesh): string => { return m.name; },

+ 28 - 1
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -38,6 +38,12 @@ module BABYLON.GLTF2 {
         _total: Nullable<number>;
     }
 
+    interface IProgressEventData {
+        lengthComputable: boolean;
+        loaded: number;
+        total: number;
+    }
+
     export class GLTFLoader implements IGLTFLoader {
         public _gltf: IGLTF;
         public _babylonScene: Scene;
@@ -77,8 +83,29 @@ module BABYLON.GLTF2 {
             GLTFLoaderExtension._Extensions.push(extension);
         }
 
+        // IE 11 Compatibility.
+        private static _progressEventFactory: (name: string, data: IProgressEventData) => ProgressEvent;
+        
+        private static _createProgressEventByConstructor(name: string, data: IProgressEventData): ProgressEvent {
+            return new ProgressEvent(name, data);
+        }
+
+        private static _createProgressEventByDocument(name: string, data: IProgressEventData): ProgressEvent {
+            const event = document.createEvent("ProgressEvent");
+            event.initProgressEvent(name, false, false, data.lengthComputable, data.loaded, data.total);
+            return event;
+        }
+
         public constructor(parent: GLTFFileLoader) {
             this._parent = parent;
+            if (!GLTFLoader._progressEventFactory) {
+                if (typeof (<any>window)["ProgressEvent"] === "function") {
+                    GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByConstructor;
+                }
+                else {
+                    GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByDocument;
+                }
+            }
         }
 
         public dispose(): void {
@@ -148,7 +175,7 @@ module BABYLON.GLTF2 {
                 total += request._total;
             }
 
-            this._progressCallback(new ProgressEvent("GLTFLoaderProgress", {
+            this._progressCallback(GLTFLoader._progressEventFactory("GLTFLoaderProgress", {
                 lengthComputable: true,
                 loaded: loaded,
                 total: total

+ 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",

+ 0 - 5
src/Audio/babylon.sound.ts

@@ -563,11 +563,6 @@ module BABYLON {
 
         private _onRegisterAfterWorldMatrixUpdate(connectedMesh: AbstractMesh): void {
             let boundingInfo = connectedMesh.getBoundingInfo();
-
-            if (!boundingInfo) {
-                return;
-            }
-
             this.setPosition(boundingInfo.boundingSphere.centerWorld);
             if (Engine.audioEngine.canUseWebAudio && this._isDirectional && this.isPlaying) {
                 this._updateDirection();

+ 1 - 1
src/Behaviors/Cameras/babylon.bouncingBehavior.ts

@@ -64,7 +64,7 @@ module BABYLON {
 					}
 
 					mesh.computeWorldMatrix(true);
-					let diagonal = (<BoundingInfo>mesh.getBoundingInfo()).diagonalLength;
+					let diagonal = mesh.getBoundingInfo().diagonalLength;
 
 					this.lowerRadiusTransitionRange = diagonal * 0.05;
 					this.upperRadiusTransitionRange = diagonal * 0.05;

+ 37 - 1
src/Behaviors/Cameras/babylon.framingBehavior.ts

@@ -224,11 +224,47 @@ module BABYLON {
 		public zoomOnMesh(mesh: AbstractMesh, focusOnOriginXZ: boolean = false, onAnimationEnd: Nullable<() => void> = null): void {
 			mesh.computeWorldMatrix(true);
 
-			let boundingBox = (<BoundingInfo>mesh.getBoundingInfo()).boundingBox;
+			let boundingBox = mesh.getBoundingInfo().boundingBox;
 			this.zoomOnBoundingInfo(boundingBox.minimumWorld, boundingBox.maximumWorld, focusOnOriginXZ, onAnimationEnd);
 		}
 
 		/**
+		 * Targets the given mesh with its children and updates zoom level accordingly.
+		 * @param mesh  The mesh to target.
+		 * @param radius Optional. If a cached radius position already exists, overrides default.
+		 * @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
+		 * @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
+		 * @param onAnimationEnd Callback triggered at the end of the framing animation
+		 */
+		public zoomOnMeshHierarchy(mesh: AbstractMesh, focusOnOriginXZ: boolean = false, onAnimationEnd: Nullable<() => void> = null): void {
+			mesh.computeWorldMatrix(true);
+
+			let boundingBox = mesh.getHierarchyBoundingVectors(true);
+			this.zoomOnBoundingInfo(boundingBox.min, boundingBox.max, focusOnOriginXZ, onAnimationEnd);
+		}
+
+		/**
+		 * Targets the given meshes with their children and updates zoom level accordingly.
+		 * @param meshes  The mesh to target.
+		 * @param radius Optional. If a cached radius position already exists, overrides default.
+		 * @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
+		 * @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
+		 * @param onAnimationEnd Callback triggered at the end of the framing animation
+		 */
+		public zoomOnMeshesHierarchy(meshes: AbstractMesh[], focusOnOriginXZ: boolean = false, onAnimationEnd: Nullable<() => void> = null): void {
+			let min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+            let max = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
+            
+			for (let i = 0; i < meshes.length; i++) {
+				let boundingInfo = meshes[i].getHierarchyBoundingVectors(true);
+				BABYLON.Tools.CheckExtends(boundingInfo.min, min, max);
+                BABYLON.Tools.CheckExtends(boundingInfo.max, min, max);
+			}
+	
+			this.zoomOnBoundingInfo(min, max, focusOnOriginXZ, onAnimationEnd);
+		}
+
+		/**
 		 * Targets the given mesh and updates zoom level accordingly.
 		 * @param mesh  The mesh to target.
 		 * @param radius Optional. If a cached radius position already exists, overrides default.

+ 2 - 2
src/Collisions/babylon.collisionCoordinator.ts

@@ -139,7 +139,7 @@ module BABYLON {
             var submeshes: Array<SerializedSubMesh> = [];
             if (mesh.subMeshes) {
                 submeshes = mesh.subMeshes.map(function (sm, idx) {
-                    let boundingInfo = <BoundingInfo>sm.getBoundingInfo();
+                    let boundingInfo = sm.getBoundingInfo();
 
                     return {
                         position: idx,
@@ -165,7 +165,7 @@ module BABYLON {
                 geometryId = geometry ? geometry.id : null;
             }
 
-            let boundingInfo = <BoundingInfo>mesh.getBoundingInfo();
+            let boundingInfo = mesh.getBoundingInfo();
 
             return {
                 uniqueId: mesh.uniqueId,

+ 2 - 2
src/Culling/Octrees/babylon.octree.ts

@@ -97,14 +97,14 @@
 
         public static CreationFuncForMeshes = (entry: AbstractMesh, block: OctreeBlock<AbstractMesh>): void => {
             let boundingInfo = entry.getBoundingInfo();
-            if (!entry.isBlocked && boundingInfo && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
+            if (!entry.isBlocked && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
                 block.entries.push(entry);
             }
         }
 
         public static CreationFuncForSubMeshes = (entry: SubMesh, block: OctreeBlock<SubMesh>): void => {
             let boundingInfo = entry.getBoundingInfo();
-            if (boundingInfo && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
+            if (boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
                 block.entries.push(entry);
             }
         }

+ 16 - 6
src/Culling/babylon.ray.ts

@@ -331,16 +331,26 @@
             return -1;
         }
 
+        public update(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray {
+            Vector3.UnprojectFloatsToRef(x, y, 0, viewportWidth, viewportHeight, world, view, projection, this.origin);
+            Vector3.UnprojectFloatsToRef(x, y, 1, viewportWidth, viewportHeight, world, view, projection, Tmp.Vector3[0]);
+
+            Tmp.Vector3[0].subtractToRef(this.origin, this.direction);
+            this.direction.normalize();
+            return this;
+        }
+
         // Statics
-        public static CreateNew(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray {
-            var start = Vector3.Unproject(new Vector3(x, y, 0), viewportWidth, viewportHeight, world, view, projection);
-            var end = Vector3.Unproject(new Vector3(x, y, 1), viewportWidth, viewportHeight, world, view, projection);
+        public static Zero(): Ray {
+            return new Ray(Vector3.Zero(), Vector3.Zero());
+        }
 
-            var direction = end.subtract(start);
-            direction.normalize();
+        public static CreateNew(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray {
+            let result = Ray.Zero();
 
-            return new Ray(start, direction);
+            return result.update(x, y, viewportWidth, viewportHeight, world, view, projection);
         }
+        
 
         /**
         * Function will create a new transformed ray starting from origin and ending at the end point. Ray's length will be set, and ray will be

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

@@ -531,7 +531,7 @@
         }
 
         public static get Version(): string {
-            return "3.1-beta-3";
+            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;

+ 0 - 5
src/Lights/babylon.directionalLight.ts

@@ -118,11 +118,6 @@
                     }
 
                     var boundingInfo = mesh.getBoundingInfo();
-
-                    if (!boundingInfo) {
-                        continue;
-                    }
-
                     var boundingBox = boundingInfo.boundingBox;
 
                     for (var index = 0; index < boundingBox.vectorsWorld.length; index++) {

+ 6 - 6
src/Loading/babylon.sceneLoader.ts

@@ -125,15 +125,15 @@
                 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);
         }
 

+ 20 - 7
src/Math/babylon.math.ts

@@ -1731,19 +1731,32 @@
         }
 
         public static Unproject(source: Vector3, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Vector3 {
+            let result = Vector3.Zero();
+
+            Vector3.UnprojectToRef(source, viewportWidth, viewportHeight, world, view, projection, result);
+
+            return result;
+        }
+
+        public static UnprojectToRef(source: Vector3, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix, result: Vector3): void {
+            Vector3.UnprojectFloatsToRef(source.x, source.y, source.z, viewportWidth, viewportHeight, world, view, projection, result);
+        }
+
+        public static UnprojectFloatsToRef(sourceX: float, sourceY: float, sourceZ: float, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix, result: Vector3): void {
             var matrix = MathTmp.Matrix[0];
             world.multiplyToRef(view, matrix)
             matrix.multiplyToRef(projection, matrix);
             matrix.invert();
-            var screenSource = new Vector3(source.x / viewportWidth * 2 - 1, -(source.y / viewportHeight * 2 - 1), 2 * source.z - 1.0);
-            var vector = Vector3.TransformCoordinates(screenSource, matrix);
+            var screenSource = MathTmp.Vector3[0];
+            screenSource.x = sourceX / viewportWidth * 2 - 1;
+            screenSource.y = -(sourceY/ viewportHeight * 2 - 1);
+            screenSource.z = 2 * sourceZ - 1.0;
+            Vector3.TransformCoordinatesToRef(screenSource, matrix, result);
             var num = screenSource.x * matrix.m[3] + screenSource.y * matrix.m[7] + screenSource.z * matrix.m[11] + matrix.m[15];
 
             if (Scalar.WithinEpsilon(num, 1.0)) {
-                vector = vector.scale(1.0 / num);
+                result.scaleInPlace(1.0 / num);
             }
-
-            return vector;
         }
 
         public static Minimize(left: Vector3, right: Vector3): Vector3 {
@@ -4690,7 +4703,7 @@
          * Returns the updated Path2.   
          */
         public addLineTo(x: number, y: number): Path2 {
-            if (closed) {
+            if (this.closed) {
                 //Tools.Error("cannot add lines to closed paths");
                 return this;
             }
@@ -4706,7 +4719,7 @@
          * Returns the updated Path2.  
          */
         public addArcTo(midX: number, midY: number, endX: number, endY: number, numberOfSegments = 36): Path2 {
-            if (closed) {
+            if (this.closed) {
                 //Tools.Error("cannot add arcs to closed paths");
                 return this;
             }

+ 4 - 14
src/Mesh/babylon.abstractMesh.ts

@@ -879,7 +879,7 @@
             let max: Vector3;
             let boundingInfo = this.getBoundingInfo();
 
-            if (!this.subMeshes || !boundingInfo) {
+            if (!this.subMeshes) {
                 min = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
                 max = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
             } else {
@@ -896,7 +896,7 @@
                     childMesh.computeWorldMatrix(true);
                     let childBoundingInfo = childMesh.getBoundingInfo();
 
-                    if (childMesh.getTotalVertices() === 0 || !childBoundingInfo) {
+                    if (childMesh.getTotalVertices() === 0) {
                         continue;
                     }
                     let boundingBox = childBoundingInfo.boundingBox;
@@ -1115,10 +1115,8 @@
             let boundingInfo = this.getBoundingInfo();
 
             // Update octree
-            if (boundingInfo) {
-                var bbox = boundingInfo.boundingBox;
-                this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
-            }
+            var bbox = boundingInfo.boundingBox;
+            this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
 
             return this._submeshesOctree;
         }
@@ -1501,10 +1499,6 @@
             var normals = this.getVerticesData(VertexBuffer.NormalKind);
             var bInfo = this.getBoundingInfo();
 
-            if (!bInfo) {
-                return this;
-            }
-
             if (this._facetDepthSort && !this._facetDepthSortEnabled) {
                 // init arrays, matrix and sort function on first call
                 this._facetDepthSortEnabled = true;
@@ -1661,10 +1655,6 @@
         public getFacetsAtLocalCoordinates(x: number, y: number, z: number): Nullable<number[]> {
             var bInfo = this.getBoundingInfo();
 
-            if (!bInfo) {
-                return null;
-            }
-
             var ox = Math.floor((x - bInfo.minimum.x * this._partitioningBBoxRatio) * this._subDiv.X * this._partitioningBBoxRatio / this._bbSize.x);
             var oy = Math.floor((y - bInfo.minimum.y * this._partitioningBBoxRatio) * this._subDiv.Y * this._partitioningBBoxRatio / this._bbSize.y);
             var oz = Math.floor((z - bInfo.minimum.z * this._partitioningBBoxRatio) * this._subDiv.Z * this._partitioningBBoxRatio / this._bbSize.z);

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

@@ -178,9 +178,7 @@
         public refreshBoundingInfo(): InstancedMesh {
             var meshBB = this._sourceMesh.getBoundingInfo();
 
-            if (meshBB) {
-                this._boundingInfo = new BoundingInfo(meshBB.minimum.clone(), meshBB.maximum.clone());
-            }
+            this._boundingInfo = new BoundingInfo(meshBB.minimum.clone(), meshBB.maximum.clone());
 
             this._updateBoundingInfo();
             return this;
@@ -210,10 +208,6 @@
 
             let boundingInfo = this.getBoundingInfo();
 
-            if (!boundingInfo) {
-                return this;
-            }
-
             this._currentLOD = <Mesh>this.sourceMesh.getLOD(camera, boundingInfo.boundingSphere);
 
             if (this._currentLOD === this.sourceMesh) {

+ 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);

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

@@ -372,10 +372,6 @@
             } else {
                 let boundingInfo = this.getBoundingInfo();
 
-                if (!boundingInfo) {
-                    return this;
-                }
-
                 bSphere =  boundingInfo.boundingSphere;
             }
 
@@ -3178,10 +3174,6 @@
             meshes.forEach(function (mesh, index, array) {
                 let boundingInfo = mesh.getBoundingInfo();
 
-                if (!boundingInfo) {
-                    return;
-                }
-
                 let boundingBox = boundingInfo.boundingBox;
                 if (!minVector || !maxVector) {
                     minVector = boundingBox.minimumWorld;

+ 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;
         }
 

+ 3 - 11
src/Mesh/babylon.subMesh.ts

@@ -24,7 +24,7 @@
 
         private _mesh: AbstractMesh;
         private _renderingMesh: Mesh;
-        private _boundingInfo: Nullable<BoundingInfo>;
+        private _boundingInfo: BoundingInfo;
         private _linesIndexBuffer: Nullable<WebGLBuffer>;
         public _lastColliderWorldVertices: Nullable<Vector3[]>;
         public _trianglePlanes: Plane[];
@@ -64,7 +64,7 @@
         /**
          * Returns the submesh BoudingInfo object.  
          */
-        public getBoundingInfo(): Nullable<BoundingInfo> {
+        public getBoundingInfo(): BoundingInfo {
             if (this.IsGlobal) {
                 return this._mesh.getBoundingInfo();
             }
@@ -134,7 +134,7 @@
             var data = this._renderingMesh.getVerticesData(VertexBuffer.PositionKind);
 
             if (!data) {
-                this._boundingInfo = this._mesh._boundingInfo;
+                this._boundingInfo = this._mesh.getBoundingInfo();
                 return this;
             }
 
@@ -145,10 +145,6 @@
             if (this.indexStart === 0 && this.indexCount === indices.length) {
                 let boundingInfo = this._renderingMesh.getBoundingInfo();
 
-                if (!boundingInfo) {
-                    return this;
-                }
-
                 //the rendering mesh's bounding info can be used, it is the standard submesh for all indices.
                 extend = { minimum: boundingInfo.minimum.clone(), maximum: boundingInfo.maximum.clone() };
             } else {
@@ -161,10 +157,6 @@
         public _checkCollision(collider: Collider): boolean {
             let boundingInfo = this._renderingMesh.getBoundingInfo();
 
-            if (!boundingInfo) {
-                return false;
-            }
-
             return boundingInfo._checkCollision(collider);
         }
 

+ 1 - 3
src/Particles/babylon.solidParticleSystem.ts

@@ -1038,9 +1038,7 @@
 
                 let boundingInfo = this.mesh.getBoundingInfo();
 
-                if (boundingInfo) {
-                    boundingInfo.isLocked = val;
-                }
+                boundingInfo.isLocked = val;
             }
     
             public get isVisibilityBoxLocked(): boolean {

+ 2 - 2
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -331,7 +331,7 @@
             //For now pointDepth will not be used and will be automatically calculated.
             //Future reference - try and find the best place to add a reference to the pointDepth variable.
             var arraySize = pointDepth || ~~(Math.sqrt(pos.length / 3) - 1);
-            let boundingInfo = <BoundingInfo>(object.getBoundingInfo());
+            let boundingInfo = object.getBoundingInfo();
             var dim = Math.min(boundingInfo.boundingBox.extendSizeWorld.x, boundingInfo.boundingBox.extendSizeWorld.y);
             var minY = boundingInfo.boundingBox.extendSizeWorld.z;
 
@@ -418,7 +418,7 @@
             //If it is a heightfield, if should be centered.
             if (impostor.type === PhysicsImpostor.HeightmapImpostor) {
                 var mesh = <AbstractMesh>(<any>object);
-                let boundingInfo = <BoundingInfo>mesh.getBoundingInfo();
+                let boundingInfo = mesh.getBoundingInfo();
                 //calculate the correct body position:
                 var rotationQuaternion = mesh.rotationQuaternion;
                 mesh.rotationQuaternion = this._tmpUnityRotation;

+ 2 - 10
src/Physics/babylon.physicsImpostor.ts

@@ -15,7 +15,7 @@ module BABYLON {
         scaling: Vector3;
         rotation?: Vector3;
         parent?: any;
-        getBoundingInfo(): Nullable<BoundingInfo>;
+        getBoundingInfo(): BoundingInfo;
         computeWorldMatrix(force: boolean): Matrix;
         getWorldMatrix?(): Matrix;
         getChildMeshes?(directDescendantsOnly?: boolean): Array<AbstractMesh>;
@@ -234,12 +234,7 @@ module BABYLON {
                 //calculate the world matrix with no rotation
                 this.object.computeWorldMatrix && this.object.computeWorldMatrix(true);
                 let boundingInfo = this.object.getBoundingInfo();
-                let size: Vector3;
-                if (boundingInfo) {
-                    size = boundingInfo.boundingBox.extendSizeWorld.scale(2)
-                } else {
-                    size = Vector3.Zero();
-                }
+                let size = boundingInfo.boundingBox.extendSizeWorld.scale(2)
 
                 //bring back the rotation
                 this.object.rotationQuaternion = q;
@@ -255,9 +250,6 @@ module BABYLON {
         public getObjectCenter(): Vector3 {
             if (this.object.getBoundingInfo) {
                 let boundingInfo = this.object.getBoundingInfo();
-                if (!boundingInfo) {
-                    return this.object.position;
-                }
                 return boundingInfo.boundingBox.centerWorld;
             } else {
                 return this.object.position;

+ 2 - 2
src/Rendering/babylon.depthRenderer.ts

@@ -34,8 +34,8 @@
                     return;
                 }
 
-                // Culling
-                engine.setState(material.backFaceCulling);
+                // Culling and reverse (right handed system)
+                engine.setState(material.backFaceCulling, 0, false, scene.useRightHandedSystem);
 
                 // Managing instances
                 var batch = mesh._getInstancesRenderList(subMesh._id);

+ 1 - 1
src/Rendering/babylon.renderingGroup.ts

@@ -187,7 +187,7 @@
             for (; subIndex < subMeshes.length; subIndex++) {
                 subMesh = subMeshes.data[subIndex];
                 subMesh._alphaIndex = subMesh.getMesh().alphaIndex;
-                subMesh._distanceToCamera = (<BoundingInfo>subMesh.getBoundingInfo()).boundingSphere.centerWorld.subtract(cameraPosition).length();
+                subMesh._distanceToCamera = subMesh.getBoundingInfo().boundingSphere.centerWorld.subtract(cameraPosition).length();
             }
 
             let sortedArray = subMeshes.data.slice(0, subMeshes.length);

Разлика између датотеке није приказан због своје велике величине
+ 68 - 48
src/Tools/babylon.tools.ts


+ 147 - 124
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
@@ -522,7 +522,6 @@
         private _meshPickProceed = false;
 
         private _previousButtonPressed: number;
-        private _previousHasSwiped = false;
         private _currentPickResult: Nullable<PickingInfo> = null;
         private _previousPickResult: Nullable<PickingInfo> = null;
         private _totalPointersPressed = 0;
@@ -554,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
          */
@@ -1117,7 +1116,7 @@
 
         public getRenderTargetsDuration(): number {
             Tools.Warn("getRenderTargetsDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;            
+            return 0;
         }
 
         public getRenderDuration(): number {
@@ -1201,7 +1200,7 @@
         }
 
         private _processPointerMove(pickResult: Nullable<PickingInfo>, evt: PointerEvent): Scene {
-            
+
             var canvas = this._engine.getRenderingCanvas();
 
             if (!canvas) {
@@ -1253,7 +1252,7 @@
                 }
             }
 
-            return this;            
+            return this;
         }
 
         /**
@@ -1264,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) {
@@ -1331,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) {
@@ -1506,7 +1505,6 @@
                                     this._previousStartingPointerPosition.x = this._startingPointerPosition.x;
                                     this._previousStartingPointerPosition.y = this._startingPointerPosition.y;
                                     this._previousButtonPressed = btn;
-                                    this._previousHasSwiped = clickInfo.hasSwiped;
                                     if (Scene.ExclusiveDoubleClickMode) {
                                         if (this._previousDelayedSimpleClickTimeout) {
                                             clearTimeout(this._previousDelayedSimpleClickTimeout);
@@ -1527,7 +1525,6 @@
                                 this._previousStartingPointerPosition.x = this._startingPointerPosition.x;
                                 this._previousStartingPointerPosition.y = this._startingPointerPosition.y;
                                 this._previousButtonPressed = btn;
-                                this._previousHasSwiped = clickInfo.hasSwiped;
                             }
                         }
                     }
@@ -1563,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);
             };
@@ -1646,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()) {
@@ -1765,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);
             });
@@ -1839,7 +1836,7 @@
             this.onKeyboardObservable.clear();
             this.onPreKeyboardObservable.clear();
             this.onPointerObservable.clear();
-            this.onPrePointerObservable.clear();     
+            this.onPrePointerObservable.clear();
         }
 
         // Ready
@@ -2085,7 +2082,7 @@
             this._useAlternateCameraConfiguration = active;
         }
 
-        public getViewMatrix(): Matrix {            
+        public getViewMatrix(): Matrix {
             return this._useAlternateCameraConfiguration ? this._alternateViewMatrix : this._viewMatrix;
         }
 
@@ -2148,7 +2145,7 @@
             if (!this._alternateSceneUbo) {
                 this._createAlternateUbo();
             }
-            
+
             if (this._alternateSceneUbo.useUbo) {
                 this._alternateSceneUbo.updateMatrix("viewProjection", this._alternateTransformMatrix);
                 this._alternateSceneUbo.updateMatrix("view", this._alternateViewMatrix);
@@ -2189,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);
@@ -2623,7 +2620,7 @@
             return this.transformNodes.filter(function (m) {
                 return m.id === id;
             })
-        }        
+        }
 
         /**
          * Get a mesh with its auto-generated unique id
@@ -2672,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) {
@@ -2755,7 +2752,7 @@
             }
 
             return null;
-        }        
+        }
 
         public getSoundByName(name: string): Nullable<Sound> {
             var index: number;
@@ -2903,9 +2900,7 @@
                 if (mesh.showSubMeshesBoundingBox) {
                     let boundingInfo = subMesh.getBoundingInfo();
 
-                    if (boundingInfo) {
-                        this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
-                    }
+                    this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
                 }
 
                 if (material) {
@@ -2928,7 +2923,7 @@
         public _isInIntermediateRendering(): boolean {
             return this._intermediateRendering
         }
-        
+
         private _activeMeshesFrozen = false;
 
         /**
@@ -2939,7 +2934,7 @@
             this._activeMeshesFrozen = true;
             return this;
         }
-        
+
         /**
          * Use this function to restart evaluating active meshes on every frame
          */
@@ -3015,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);
@@ -3062,9 +3057,7 @@
             if (sourceMesh.showBoundingBox || this.forceShowBoundingBoxes) {
                 let boundingInfo = sourceMesh.getBoundingInfo();
 
-                if (boundingInfo) {
-                    this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);    
-                }
+                this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
             }
 
             if (mesh && mesh.subMeshes) {
@@ -3114,7 +3107,7 @@
                 throw new Error("Active camera not set");
 
             Tools.StartPerformanceCounter("Rendering camera " + this.activeCamera.name);
-           
+
             // Viewport
             engine.setViewport(this.activeCamera.viewport);
 
@@ -3218,7 +3211,7 @@
                 }
                 engine.setDepthBuffer(true);
             }
-        
+
             // Activate HighlightLayer stencil
             if (renderhighlights) {
                 this._engine.setStencilBuffer(true);
@@ -3277,7 +3270,7 @@
 
             // Finalize frame
             this.postProcessManager._finalizeFrame(camera.isIntermediate);
-           
+
             // Reset some special arrays
             this._renderTargets.reset();
 
@@ -3298,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]);
@@ -3375,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
 
-              var defaultTimeStep = (60.0 / 1000.0);
-              if (this._physicsEngine) {
-                defaultTimeStep = this._physicsEngine.getTimeStep();
-              }
+                if (this._physicsEngine) {
+                    defaultFrameTime = this._physicsEngine.getTimeStep() / 1000; //timestep in physics engine is in seconds
+                }
+                let stepsTaken = 0;
 
-              var maxSubSteps = this._engine.getLockstepMaxSteps();
+                var maxSubSteps = this._engine.getLockstepMaxSteps();
 
-              this._timeAccumulator += deltaTime;
+                var internalSteps = Math.floor(deltaTime / (1000 * defaultFPS));
+                internalSteps = Math.min(internalSteps, maxSubSteps);
 
-              // 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);
+                do {
+                    this.onBeforeStepObservable.notifyObservers(this);
 
-              for(this._currentInternalStep = 0; this._currentInternalStep < internalSteps; this._currentInternalStep++){
+                    // Animations
+                    this._animationRatio = defaultFrameTime * defaultFPS;
+                    this._animate();
+                    this.onAfterAnimationsObservable.notifyObservers(this);
 
-                this.onBeforeStepObservable.notifyObservers(this);
+                    // Physics
+                    if (this._physicsEngine) {
+                        this.onBeforePhysicsObservable.notifyObservers(this);
+                        this._physicsEngine._step(defaultFPS);
+                        this.onAfterPhysicsObservable.notifyObservers(this);
+                    }
+
+                    this.onAfterStepObservable.notifyObservers(this);
+                    this._currentStepId++;
+
+                    if ((internalSteps > 1) && (stepsTaken != internalSteps - 1)) {
+                        this._evaluateActiveMeshes();
+                    }
 
+                    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.onBeforePhysicsObservable.notifyObservers(this);
+                    this._physicsEngine._step(deltaTime / 1000.0);
+                    this.onAfterPhysicsObservable.notifyObservers(this);
                 }
-                this._timeAccumulator -= defaultTimeStep;
-
-                this.onAfterStepObservable.notifyObservers(this);
-                this._currentStepId++;
-
-                if((internalSteps > 1) && (this._currentInternalStep != internalSteps - 1)) {
-                    this._evaluateActiveMeshes();
-                }
-              }
-            }
-            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
@@ -3957,13 +3956,11 @@
                 mesh.computeWorldMatrix(true);
                 let boundingInfo = mesh.getBoundingInfo();
 
-                if (boundingInfo) {
-                    var minBox = boundingInfo.boundingBox.minimumWorld;
-                    var maxBox = boundingInfo.boundingBox.maximumWorld;
+                var minBox = boundingInfo.boundingBox.minimumWorld;
+                var maxBox = boundingInfo.boundingBox.maximumWorld;
 
-                    Tools.CheckExtends(minBox, min, max);
-                    Tools.CheckExtends(maxBox, min, max);
-                }
+                Tools.CheckExtends(minBox, min, max);
+                Tools.CheckExtends(maxBox, min, max);
             }
 
             return {
@@ -3987,6 +3984,14 @@
 
         // Picking
         public createPickingRay(x: number, y: number, world: Matrix, camera: Nullable<Camera>, cameraViewSpace = false): Ray {
+            let result = Ray.Zero();
+
+            this.createPickingRayToRef(x, y, world, result, camera, cameraViewSpace);
+
+            return result;
+        }
+
+        public createPickingRayToRef(x: number, y: number, world: Matrix, result: Ray, camera: Nullable<Camera>, cameraViewSpace = false): Scene {
             var engine = this._engine;
 
             if (!camera) {
@@ -4002,13 +4007,22 @@
             // 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);
-            return Ray.CreateNew(x, y, viewport.width, viewport.height, world ? world : Matrix.Identity(), cameraViewSpace ? Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
-            //       return BABYLON.Ray.CreateNew(x / window.devicePixelRatio, y / window.devicePixelRatio, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), camera.getViewMatrix(), camera.getProjectionMatrix());
+
+            result.update(x, y, viewport.width, viewport.height, world ? world : Matrix.Identity(), cameraViewSpace ? Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
+            return this;
         }
 
-        public createPickingRayInCameraSpace(x: number, y: number, camera?: Camera): Nullable<Ray> {
+        public createPickingRayInCameraSpace(x: number, y: number, camera?: Camera): Ray {
+            let result = Ray.Zero();
+
+            this.createPickingRayInCameraSpaceToRef(x, y, result, camera);
+
+            return result;
+        }
+
+        public createPickingRayInCameraSpaceToRef(x: number, y: number, result: Ray, camera?: Camera): Scene {
             if (!BABYLON.PickingInfo) {
-                return null;
+                return this;
             }
 
             var engine = this._engine;
@@ -4027,7 +4041,8 @@
             // 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);
-            return Ray.CreateNew(x, y, viewport.width, viewport.height, identity, identity, camera.getProjectionMatrix());
+            result.update(x, y, viewport.width, viewport.height, identity, identity, camera.getProjectionMatrix());
+            return this;
         }
 
         private _internalPick(rayFunction: (world: Matrix) => Ray, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean): Nullable<PickingInfo> {
@@ -4139,6 +4154,8 @@
             return pickingInfo || new PickingInfo();
         }
 
+        private _tempPickingRay: Ray;
+
         /** Launch a ray to try to pick a mesh in the scene
          * @param x position on screen
          * @param y position on screen
@@ -4147,7 +4164,14 @@
          * @param camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used
          */
         public pick(x: number, y: number, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean, camera?: Nullable<Camera>): Nullable<PickingInfo> {
-            return this._internalPick(world => this.createPickingRay(x, y, world, camera || null), predicate, fastCheck);
+            if (!this._tempPickingRay) {
+                this._tempPickingRay = Ray.Zero();
+            }
+
+            return this._internalPick(world => {
+                this.createPickingRayToRef(x, y, world, this._tempPickingRay, camera || null);
+                return this._tempPickingRay;
+            }, predicate, fastCheck);
         }
 
         /** Launch a ray to try to pick a sprite in the scene
@@ -4158,13 +4182,12 @@
          * @param camera camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used
          */
         public pickSprite(x: number, y: number, predicate?: (sprite: Sprite) => boolean, fastCheck?: boolean, camera?: Camera): Nullable<PickingInfo> {
-            let ray = this.createPickingRayInCameraSpace(x, y, camera);
-
-            if (!ray) {
-                return null;
+            if (!this._tempPickingRay) {
+                this._tempPickingRay = Ray.Zero();
             }
+            this.createPickingRayInCameraSpaceToRef(x, y, this._tempPickingRay, camera);
 
-            return this._internalPickSprites(ray, predicate, fastCheck, camera);
+            return this._internalPickSprites(this._tempPickingRay, predicate, fastCheck, camera);
         }
 
         private _cachedRayForTransform: Ray;
@@ -4182,9 +4205,9 @@
                 world.invertToRef(this._pickWithRayInverseMatrix);
 
                 if (!this._cachedRayForTransform) {
-                    this._cachedRayForTransform = new Ray(Vector3.Zero(), Vector3.Zero());
+                    this._cachedRayForTransform = Ray.Zero();
                 }
-                
+
                 Ray.TransformToRef(ray, this._pickWithRayInverseMatrix, this._cachedRayForTransform);
                 return this._cachedRayForTransform;
             }, predicate, fastCheck);
@@ -4214,9 +4237,9 @@
                 world.invertToRef(this._pickWithRayInverseMatrix);
 
                 if (!this._cachedRayForTransform) {
-                    this._cachedRayForTransform = new Ray(Vector3.Zero(), Vector3.Zero());
+                    this._cachedRayForTransform = Ray.Zero();
                 }
-                
+
                 Ray.TransformToRef(ray, this._pickWithRayInverseMatrix, this._cachedRayForTransform);
                 return this._cachedRayForTransform;
             }, predicate);
@@ -4320,7 +4343,7 @@
 
             if (this.postProcessManager) {
                 this.postProcessManager._rebuild();
-            }         
+            }
 
             for (var layer of this.layers) {
                 layer._rebuild();
@@ -4340,7 +4363,7 @@
 
             if (this._postProcessRenderPipelineManager) {
                 this._postProcessRenderPipelineManager._rebuild();
-            }            
+            }
         }
 
         public _rebuildTextures(): void {

BIN
tests/validation/ReferenceImages/gltfMaterial.png


BIN
tests/validation/ReferenceImages/gltfMaterialAlpha.png


+ 0 - 0
tests/validation/ReferenceImages/gltfMaterialMetallicRoughness.png


Неке датотеке нису приказане због велике количине промена