Переглянути джерело

Merge branch 'master' into adtInvalidateRect

Trevor Baron 6 роки тому
батько
коміт
5f7c657df9
79 змінених файлів з 35016 додано та 33147 видалено
  1. 9394 9267
      Playground/babylon.d.txt
  2. 405 405
      Playground/index.html
  3. 7 3
      Viewer/src/model/viewerModel.ts
  4. 21903 21862
      dist/preview release/babylon.d.ts
  5. 1 1
      dist/preview release/babylon.js
  6. 226 121
      dist/preview release/babylon.max.js
  7. 226 121
      dist/preview release/babylon.no-module.max.js
  8. 1 1
      dist/preview release/babylon.worker.js
  9. 226 121
      dist/preview release/es6.js
  10. 1 1
      dist/preview release/glTF2Interface/package.json
  11. 88 0
      dist/preview release/gui/babylon.gui.d.ts
  12. 1 1
      dist/preview release/gui/babylon.gui.js
  13. 1 1
      dist/preview release/gui/babylon.gui.min.js
  14. 1 1
      dist/preview release/gui/babylon.gui.min.js.map
  15. 185 0
      dist/preview release/gui/babylon.gui.module.d.ts
  16. 2 2
      dist/preview release/gui/package.json
  17. 7 7
      dist/preview release/inspector/babylon.inspector.bundle.js
  18. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js.map
  19. 5 5
      dist/preview release/inspector/package.json
  20. 3 3
      dist/preview release/loaders/package.json
  21. 106 0
      dist/preview release/materialsLibrary/babylon.skyMaterial.d.ts
  22. 113 6
      dist/preview release/materialsLibrary/babylon.skyMaterial.js
  23. 1 1
      dist/preview release/materialsLibrary/babylon.skyMaterial.min.js
  24. 106 0
      dist/preview release/materialsLibrary/babylonjs.materials.d.ts
  25. 113 6
      dist/preview release/materialsLibrary/babylonjs.materials.js
  26. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  27. 106 0
      dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts
  28. 2 2
      dist/preview release/materialsLibrary/package.json
  29. 2 2
      dist/preview release/postProcessesLibrary/package.json
  30. 2 2
      dist/preview release/proceduralTexturesLibrary/package.json
  31. 3 3
      dist/preview release/serializers/package.json
  32. 1 15
      dist/preview release/viewer/babylon.viewer.d.ts
  33. 1 1
      dist/preview release/viewer/babylon.viewer.js
  34. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  35. 1 18
      dist/preview release/viewer/babylon.viewer.module.d.ts
  36. 9 0
      dist/preview release/what's new.md
  37. 122 0
      gui/src/2D/adtInstrumentation.ts
  38. 970 941
      gui/src/2D/advancedDynamicTexture.ts
  39. 2 2
      gui/src/2D/controls/container.ts
  40. 3 0
      gui/src/2D/controls/grid.ts
  41. 27 0
      gui/src/2D/controls/scrollViewers/scrollViewer.ts
  42. 1 0
      gui/src/2D/index.ts
  43. 16 4
      inspector/src/components/actionTabs/actionTabs.scss
  44. 3 2
      inspector/src/components/actionTabs/actionTabsComponent.tsx
  45. 21 2
      inspector/src/components/actionTabs/lines/color3LineComponent.tsx
  46. 1 1
      inspector/src/components/actionTabs/lines/floatLineComponent.tsx
  47. 1 1
      inspector/src/components/actionTabs/lines/numericInputComponent.tsx
  48. 7 3
      inspector/src/components/actionTabs/lines/textureLineComponent.tsx
  49. 1 1
      inspector/src/components/actionTabs/lines/vector3LineComponent.tsx
  50. 1 1
      inspector/src/components/actionTabs/paneComponent.tsx
  51. 22 1
      inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx
  52. 1 0
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx
  53. 61 0
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMetallicRoughnessMaterialPropertyGridComponent.tsx
  54. 60 0
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrSpecularGlossinessMaterialPropertyGridComponent.tsx
  55. 31 2
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/texturePropertyGridComponent.tsx
  56. 2 0
      inspector/src/components/globalState.ts
  57. 4 0
      inspector/src/components/sceneExplorer/sceneExplorerComponent.tsx
  58. 2 2
      inspector/src/tools.ts
  59. 111 15
      materialsLibrary/src/sky/babylon.skyMaterial.ts
  60. 3 2
      materialsLibrary/src/sky/sky.fragment.fx
  61. 1 1
      package.json
  62. 34 33
      src/Cameras/Inputs/babylon.arcRotateCameraKeyboardMoveInput.ts
  63. 27 26
      src/Cameras/Inputs/babylon.freeCameraKeyboardMoveInput.ts
  64. 11 2
      src/Culling/babylon.boundingInfo.ts
  65. 19 2
      src/Culling/babylon.boundingSphere.ts
  66. 17 2
      src/Debug/babylon.debugLayer.ts
  67. 3 5
      src/Engine/babylon.engine.ts
  68. 30 6
      src/Materials/Textures/babylon.baseTexture.ts
  69. 1 1
      src/Materials/Textures/babylon.dynamicTexture.ts
  70. 14 7
      src/Materials/Textures/babylon.texture.ts
  71. 2 2
      src/Materials/Textures/babylon.videoTexture.ts
  72. 2 2
      src/Materials/babylon.standardMaterial.ts
  73. 42 3
      src/Mesh/babylon.abstractMesh.ts
  74. 23 15
      src/Mesh/babylon.geometry.ts
  75. 3 1
      src/Mesh/babylon.mesh.ts
  76. 16 16
      src/Mesh/babylon.meshBuilder.ts
  77. 18 33
      src/Tools/babylon.khronosTextureContainer.ts
  78. 1 1
      src/Tools/babylon.textureTools.ts
  79. 26 26
      src/babylon.scene.ts

Різницю між файлами не показано, бо вона завелика
+ 9394 - 9267
Playground/babylon.d.txt


+ 405 - 405
Playground/index.html

@@ -1,490 +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="js/libs/pep.min.js"></script>
-        <!--For canvas/code separator-->
-        <script src="js/libs/split.js"></script>
-
-        <script src="js/libs/dat.gui.min.js"></script>
-        <!-- jszip -->
-        <script src="js/libs/jszip.min.js"></script>
-        <script src="js/libs/fileSaver.js"></script>
-        <!-- Dependencies -->
-        <script src="https://preview.babylonjs.com/ammo.js"></script>
-        <script src="https://preview.babylonjs.com/cannon.js"></script>
-        <script src="https://preview.babylonjs.com/Oimo.js"></script>
-        <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
-        <script src="https://preview.babylonjs.com/earcut.min.js"></script>
-        <!-- Babylon.js -->
-        <script src="https://preview.babylonjs.com/babylon.js"></script>
-        <script src="https://preview.babylonjs.com/gui/babylon.gui.min.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/serializers/babylonjs.serializers.min.js"></script>
-
-        <!-- Monaco -->
-        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
-
-
-        <!-- Extensions -->
-        <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js" async></script>
-        <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js" async></script>
-        <script src="https://www.babylontoolkit.com/playground/scripts/babylon.navmesh.js"></script>
-        <script src="https://www.babylontoolkit.com/playground/scripts/babylon.manager.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="js/libs/pep.min.js"></script>
+    <!--For canvas/code separator-->
+    <script src="js/libs/split.js"></script>
+
+    <script src="js/libs/dat.gui.min.js"></script>
+    <!-- jszip -->
+    <script src="js/libs/jszip.min.js"></script>
+    <script src="js/libs/fileSaver.js"></script>
+    <!-- Dependencies -->
+    <script src="https://preview.babylonjs.com/ammo.js"></script>
+    <script src="https://preview.babylonjs.com/cannon.js"></script>
+    <script src="https://preview.babylonjs.com/Oimo.js"></script>
+    <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
+    <script src="https://preview.babylonjs.com/earcut.min.js"></script>
+    <!-- Babylon.js -->
+    <script src="https://preview.babylonjs.com/babylon.js"></script>
+    <script src="https://preview.babylonjs.com/gui/babylon.gui.min.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/serializers/babylonjs.serializers.min.js"></script>
+
+    <!-- Monaco -->
+    <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
+
+
+    <!-- Extensions -->
+    <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js" async></script>
+    <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js" async></script>
+    <!-- <script async src="https://www.babylontoolkit.com/playground/scripts/babylon.navmesh.js"></script>
+    <script async src="https://www.babylontoolkit.com/playground/scripts/babylon.manager.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 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 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 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>
+        <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 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="far fa-square" 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 class="option" id="minimapToggle1600">Minimap
-                            <i class="far fa-square" aria-hidden="true"></i>
+                    </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="far fa-square" 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 class="option" id="minimapToggle1600">Minimap
+                        <i class="far fa-square" aria-hidden="true"></i>
+                    </div>
                 </div>
-
-                <div class="button uncheck" id="debugButton1600">Inspector</div>
-                <div class="button" id="metadataButton1600">Metadata</div>
             </div>
 
+            <div class="button uncheck" id="debugButton1600">Inspector</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>
-                </div>
-                <div class="button select">
-                    <span class="examplesButton">Examples</span>
+
+        <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 class="button select">
+                <span class="examplesButton">Examples</span>
+            </div>
         </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 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 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 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>
-                        </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 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 class="option" id='safemodeToggle1475'>Safe mode
-                            <i class="far fa-square" 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="minimapToggle1475">Minimap
-                            <i class="far fa-square" aria-hidden="true"></i>
+                    </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 class="option" id="debugButton1475">Inspector</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 class="option" id='safemodeToggle1475'>Safe mode
+                        <i class="far fa-square" 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="minimapToggle1475">Minimap
+                        <i class="far fa-square" aria-hidden="true"></i>
+                    </div>
+                    <div class="option" id="debugButton1475">Inspector</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 class="category right">
-                <div class="button select">
-                    <span class="examplesButton">Examples</span>
-                </div>
+        <div class="category right">
+            <div class="button select">
+                <span class="examplesButton">Examples</span>
             </div>
         </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 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 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 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>
-                        </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 class="option" id="safemodeToggle1030">Safe mode
-                            <i class="far fa-square" aria-hidden="true"></i>
+        <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 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="minimapToggle1030">Minimap
-                            <i class="far fa-square" aria-hidden="true"></i>
+                    </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 class="option" id="debugButton1030">Inspector</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 class="option" id="safemodeToggle1030">Safe mode
+                        <i class="far fa-square" 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="minimapToggle1030">Minimap
+                        <i class="far fa-square" aria-hidden="true"></i>
+                    </div>
+                    <div class="option" id="debugButton1030">Inspector</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 class="category right">
-                <div class="button select">
-                    <span class="examplesButton">Examples</span>
-                </div>
+        <div class="category right">
+            <div class="button select">
+                <span class="examplesButton">Examples</span>
             </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="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>
+        </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="far fa-square" aria-hidden="true"></i>
+        <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 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="minimapToggle750">Minimap
-                            <i class="far fa-square" aria-hidden="true"></i>
+                    </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 class="option" id="debugButton750">Inspector</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="option" id="safemodeToggle750">Safe mode
+                        <i class="far fa-square" 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="minimapToggle750">Minimap
+                        <i class="far fa-square" aria-hidden="true"></i>
+                    </div>
+                    <div class="option" id="debugButton750">Inspector</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 class="category right">
-                <div class="button select">
-                    <span id="currentScript750">Examples</span>
-                </div>
+        <div class="category right">
+            <div class="button select">
+                <span id="currentScript750">Examples</span>
             </div>
         </div>
+    </div>
 
-        <div class="wrapper">
-            <div id="jsEditor"></div>
-            <div id="canvasZone">
-                <canvas touch-action="none" id="renderCanvas"></canvas>
-            </div>
+    <div class="wrapper">
+        <div id="jsEditor"></div>
+        <div id="canvasZone">
+            <canvas touch-action="none" id="renderCanvas"></canvas>
         </div>
-        <div id="exampleList" class="javascript">
-            <div id="exampleBanner">
-                <h1>Examples</h1>
-            </div>
-            <div class="horizontalSeparator"></div>
-            <input id="filterBar" type="text" placeholder="Filter examples...">
-            <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
+    </div>
+    <div id="exampleList" class="javascript">
+        <div id="exampleBanner">
+            <h1>Examples</h1>
         </div>
+        <div class="horizontalSeparator"></div>
+        <input id="filterBar" type="text" placeholder="Filter examples...">
+        <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
+    </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="https://forum.babylonjs.com/">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="https://forum.babylonjs.com/">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 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>
+                <div id="saveFormButtonOk" class="button">OK</div>
+                <div id="saveFormButtonCancel" class="button">Cancel</div>
             </div>
         </div>
-
-        <div id="waitDiv">
-            <span id="waitTitle">Babylon.js Playground
-                <BR>
-                <BR>
-                <BR>
-            </span>
-            <img src="waitlogo.png" id="waitLogo" />
-        </div>
-
-        <script src="js/libs/jquery.min.js"></script>
-
-        <script src="js/actions.js"></script>
-        <script src="js/pbt.js"></script>
-        <script src="js/index.js"></script>
-
-        <!-- Global site tag (gtag.js) - Google Analytics -->
-        <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
-        <script>
-            window.dataLayer = window.dataLayer || [];
-            function gtag() { dataLayer.push(arguments); }
-            gtag('js', new Date());
-
-            gtag('config', 'UA-41767310-2');
-        </script>
-    </body>
-
-</html>
+    </div>
+
+    <div id="waitDiv">
+        <span id="waitTitle">Babylon.js Playground
+            <BR>
+            <BR>
+            <BR>
+        </span>
+        <img src="waitlogo.png" id="waitLogo" />
+    </div>
+
+    <script src="js/libs/jquery.min.js"></script>
+
+    <script src="js/actions.js"></script>
+    <script src="js/pbt.js"></script>
+    <script src="js/index.js"></script>
+
+    <!-- Global site tag (gtag.js) - Google Analytics -->
+    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
+    <script>
+        window.dataLayer = window.dataLayer || [];
+        function gtag() { dataLayer.push(arguments); }
+        gtag('js', new Date());
+
+        gtag('config', 'UA-41767310-2');
+    </script>
+</body>
+
+</html>

+ 7 - 3
Viewer/src/model/viewerModel.ts

@@ -196,7 +196,11 @@ export class ViewerModel implements IDisposable {
         if (!mesh.parent) {
             mesh.parent = this._pivotMesh;
         }
-        mesh.receiveShadows = !!this.configuration.receiveShadows;
+
+        if (mesh.getClassName() !== "InstancedMesh") {
+            mesh.receiveShadows = !!this.configuration.receiveShadows;
+        }
+
         this._meshes.push(mesh);
         if (triggerLoaded) {
             return this.onLoadedObservable.notifyObserversWithPromise(this);
@@ -557,7 +561,7 @@ export class ViewerModel implements IDisposable {
                 material.disableLighting = !this._modelConfiguration.material.directEnabled;
             }
             if (this._configurationContainer && this._configurationContainer.reflectionColor) {
-                material.reflectionColor = this._configurationContainer.reflectionColor;
+                material.reflectionColor = this._configurationContainer.reflectionColor.clone();
             }
         }
         else if (material instanceof MultiMaterial) {
@@ -762,4 +766,4 @@ export class ViewerModel implements IDisposable {
         this._animations.length = 0;
         this.rootMesh.dispose(false, true);
     }
-}
+}

Різницю між файлами не показано, бо вона завелика
+ 21903 - 21862
dist/preview release/babylon.d.ts


Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/babylon.js


+ 226 - 121
dist/preview release/babylon.max.js

@@ -12974,7 +12974,7 @@ var BABYLON;
              * Returns the current version of the framework
              */
             get: function () {
-                return "4.0.0-alpha.11";
+                return "4.0.0-alpha.14";
             },
             enumerable: true,
             configurable: true
@@ -15823,8 +15823,7 @@ var BABYLON;
                         customFallback = true;
                         excludeLoaders.push(loader);
                         BABYLON.Tools.Warn(loader.constructor.name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
-                        _this.createTexture(urlArg, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture, undefined, undefined, excludeLoaders);
-                        return;
+                        _this.createTexture(urlArg, noMipmap, texture.invertY, scene, samplingMode, null, null, buffer, texture, undefined, undefined, excludeLoaders);
                     }
                 }
                 if (!customFallback) {
@@ -15832,8 +15831,7 @@ var BABYLON;
                         texture.onLoadedObservable.remove(onLoadObserver);
                     }
                     if (BABYLON.Tools.UseFallbackTexture) {
-                        _this.createTexture(BABYLON.Tools.fallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture);
-                        return;
+                        _this.createTexture(BABYLON.Tools.fallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, null, buffer, texture);
                     }
                 }
                 if (onError) {
@@ -19572,8 +19570,25 @@ var BABYLON;
          * @returns true if there is an intersection
          */
         BoundingSphere.prototype.isInFrustum = function (frustumPlanes) {
+            var center = this.centerWorld;
+            var radius = this.radiusWorld;
+            for (var i = 0; i < 6; i++) {
+                if (frustumPlanes[i].dotCoordinate(center) <= -radius) {
+                    return false;
+                }
+            }
+            return true;
+        };
+        /**
+         * Tests if the bounding sphere center is in between the frustum planes.
+         * Used for optimistic fast inclusion.
+         * @param frustumPlanes defines the frustum planes to test
+         * @returns true if the sphere center is in between the frustum planes
+         */
+        BoundingSphere.prototype.isCenterInFrustum = function (frustumPlanes) {
+            var center = this.centerWorld;
             for (var i = 0; i < 6; i++) {
-                if (frustumPlanes[i].dotCoordinate(this.centerWorld) <= -this.radiusWorld) {
+                if (frustumPlanes[i].dotCoordinate(center) < 0) {
                     return false;
                 }
             }
@@ -20010,15 +20025,22 @@ var BABYLON;
         /**
          * Returns `true` if the bounding info is within the frustum defined by the passed array of planes.
          * @param frustumPlanes defines the frustum to test
-         * @param strategy defines the strategy to use for the culling (default is BABYLON.Scene.CULLINGSTRATEGY_STANDARD)
+         * @param strategy defines the strategy to use for the culling (default is BABYLON.AbstractMesh.CULLINGSTRATEGY_STANDARD)
          * @returns true if the bounding info is in the frustum planes
          */
         BoundingInfo.prototype.isInFrustum = function (frustumPlanes, strategy) {
             if (strategy === void 0) { strategy = BABYLON.AbstractMesh.CULLINGSTRATEGY_STANDARD; }
+            var inclusionTest = (strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION || strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY);
+            if (inclusionTest) {
+                if (this.boundingSphere.isCenterInFrustum(frustumPlanes)) {
+                    return true;
+                }
+            }
             if (!this.boundingSphere.isInFrustum(frustumPlanes)) {
                 return false;
             }
-            if (strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY) {
+            var bSphereOnlyTest = (strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY || strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY);
+            if (bSphereOnlyTest) {
                 return true;
             }
             return this.boundingBox.isInFrustum(frustumPlanes);
@@ -21273,7 +21295,16 @@ var BABYLON;
             if (scene === void 0) { scene = null; }
             var _this = _super.call(this, name, scene, false) || this;
             _this._facetData = new _FacetDataStorage();
-            /** Gets ot sets the culling strategy to use to find visible meshes */
+            /**
+             * The culling strategy to use to check whether the mesh must be rendered or not.
+             * This value can be changed at any time and will be used on the next render mesh selection.
+             * The possible values are :
+             * - AbstractMesh.CULLINGSTRATEGY_STANDARD
+             * - AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY
+             * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION
+             * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY
+             * Please read each static variable documentation to get details about the culling process.
+             * */
             _this.cullingStrategy = AbstractMesh.CULLINGSTRATEGY_STANDARD;
             // Events
             /**
@@ -23074,10 +23105,40 @@ var BABYLON;
         AbstractMesh.OCCLUSION_ALGORITHM_TYPE_ACCURATE = 0;
         /** Use a conservative occlusion algorithm */
         AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE = 1;
-        /** Default culling strategy with bounding box and bounding sphere and then frustum culling */
+        /** Default culling strategy : this is an exclusion test and it's the more accurate.
+         *  Test order :
+         *  Is the bounding sphere outside the frustum ?
+         *  If not, are the bounding box vertices outside the frustum ?
+         *  It not, then the cullable object is in the frustum.
+         */
         AbstractMesh.CULLINGSTRATEGY_STANDARD = 0;
-        /** Culling strategy with bounding sphere only and then frustum culling */
+        /** Culling strategy : Bounding Sphere Only.
+         *  This is an exclusion test. It's faster than the standard strategy because the bounding box is not tested.
+         *  It's also less accurate than the standard because some not visible objects can still be selected.
+         *  Test : is the bounding sphere outside the frustum ?
+         *  If not, then the cullable object is in the frustum.
+         */
         AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY = 1;
+        /** Culling strategy : Optimistic Inclusion.
+         *  This in an inclusion test first, then the standard exclusion test.
+         *  This can be faster when a cullable object is expected to be almost always in the camera frustum.
+         *  This could also be a little slower than the standard test when the tested object center is not the frustum but one of its bounding box vertex is still inside.
+         *  Anyway, it's as accurate as the standard strategy.
+         *  Test :
+         *  Is the cullable object bounding sphere center in the frustum ?
+         *  If not, apply the default culling strategy.
+         */
+        AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION = 2;
+        /** Culling strategy : Optimistic Inclusion then Bounding Sphere Only.
+         *  This in an inclusion test first, then the bounding sphere only exclusion test.
+         *  This can be the fastest test when a cullable object is expected to be almost always in the camera frustum.
+         *  This could also be a little slower than the BoundingSphereOnly strategy when the tested object center is not in the frustum but its bounding sphere still intersects it.
+         *  It's less accurate than the standard strategy and as accurate as the BoundingSphereOnly strategy.
+         *  Test :
+         *  Is the cullable object bounding sphere center in the frustum ?
+         *  If not, apply the Bounding Sphere Only strategy. No Bounding Box is tested here.
+         */
+        AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY = 3;
         return AbstractMesh;
     }(BABYLON.TransformNode));
     BABYLON.AbstractMesh = AbstractMesh;
@@ -26372,7 +26433,7 @@ var BABYLON;
             /**
              * an optional map from Geometry Id to Geometry index in the 'geometries' array
              */
-            _this.geometriesById = null;
+            _this.geometriesByUniqueId = null;
             _this._defaultMeshCandidates = {
                 data: [],
                 length: 0
@@ -26412,10 +26473,10 @@ var BABYLON;
                 _this._imageProcessingConfiguration = new BABYLON.ImageProcessingConfiguration();
             }
             _this.setDefaultCandidateProviders();
-            if (options && options.useGeometryIdsMap === true) {
-                _this.geometriesById = {};
+            if (options && options.useGeometryUniqueIdsMap === true) {
+                _this.geometriesByUniqueId = {};
             }
-            _this.useMaterialMeshMap = options && options.useGeometryIdsMap || false;
+            _this.useMaterialMeshMap = options && options.useGeometryUniqueIdsMap || false;
             _this.useClonedMeshhMap = options && options.useClonedMeshhMap || false;
             _this._engine.onNewSceneAddedObservable.notifyObservers(_this);
             return _this;
@@ -28657,8 +28718,8 @@ var BABYLON;
          * @param newGeometry The geometry to add
          */
         Scene.prototype.addGeometry = function (newGeometry) {
-            if (this.geometriesById) {
-                this.geometriesById[newGeometry.id] = this.geometries.length;
+            if (this.geometriesByUniqueId) {
+                this.geometriesByUniqueId[newGeometry.uniqueId] = this.geometries.length;
             }
             this.geometries.push(newGeometry);
         };
@@ -28890,29 +28951,29 @@ var BABYLON;
          * @return the geometry or null if none found.
          */
         Scene.prototype.getGeometryByID = function (id) {
-            if (this.geometriesById) {
-                var index_1 = this.geometriesById[id];
+            for (var index = 0; index < this.geometries.length; index++) {
+                if (this.geometries[index].id === id) {
+                    return this.geometries[index];
+                }
+            }
+            return null;
+        };
+        Scene.prototype._getGeometryByUniqueID = function (uniqueId) {
+            if (this.geometriesByUniqueId) {
+                var index_1 = this.geometriesByUniqueId[uniqueId];
                 if (index_1 !== undefined) {
                     return this.geometries[index_1];
                 }
             }
             else {
                 for (var index = 0; index < this.geometries.length; index++) {
-                    if (this.geometries[index].id === id) {
+                    if (this.geometries[index].uniqueId === uniqueId) {
                         return this.geometries[index];
                     }
                 }
             }
             return null;
         };
-        Scene.prototype._getGeometryByUniqueID = function (id) {
-            for (var index = 0; index < this.geometries.length; index++) {
-                if (this.geometries[index].uniqueId === id) {
-                    return this.geometries[index];
-                }
-            }
-            return null;
-        };
         /**
          * Add a new geometry to this scene
          * @param geometry defines the geometry to be added to the scene.
@@ -28938,8 +28999,8 @@ var BABYLON;
          */
         Scene.prototype.removeGeometry = function (geometry) {
             var index;
-            if (this.geometriesById) {
-                index = this.geometriesById[geometry.id];
+            if (this.geometriesByUniqueId) {
+                index = this.geometriesByUniqueId[geometry.uniqueId];
                 if (index === undefined) {
                     return false;
                 }
@@ -28953,9 +29014,9 @@ var BABYLON;
             if (index !== this.geometries.length - 1) {
                 var lastGeometry = this.geometries[this.geometries.length - 1];
                 this.geometries[index] = lastGeometry;
-                if (this.geometriesById) {
-                    this.geometriesById[lastGeometry.id] = index;
-                    this.geometriesById[geometry.id] = undefined;
+                if (this.geometriesByUniqueId) {
+                    this.geometriesByUniqueId[lastGeometry.uniqueId] = index;
+                    this.geometriesByUniqueId[geometry.uniqueId] = undefined;
                 }
             }
             this.geometries.pop();
@@ -31768,14 +31829,6 @@ var BABYLON;
              */
             this.anisotropicFilteringLevel = BaseTexture.DEFAULT_ANISOTROPIC_FILTERING_LEVEL;
             /**
-             * Define if the texture is a cube texture or if false a 2d texture.
-             */
-            this.isCube = false;
-            /**
-             * Define if the texture is a 3d texture (webgl 2) or if false a 2d texture.
-             */
-            this.is3D = false;
-            /**
              * Define if the texture contains data in gamma space (most of the png/jpg aside bump).
              * HDR texture are usually stored in linear space.
              * This only impacts the PBR and Background materials
@@ -31864,6 +31917,44 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(BaseTexture.prototype, "isCube", {
+            /**
+             * Define if the texture is a cube texture or if false a 2d texture.
+             */
+            get: function () {
+                if (!this._texture) {
+                    return false;
+                }
+                return this._texture.isCube;
+            },
+            set: function (value) {
+                if (!this._texture) {
+                    return;
+                }
+                this._texture.isCube = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(BaseTexture.prototype, "is3D", {
+            /**
+             * Define if the texture is a 3d texture (webgl 2) or if false a 2d texture.
+             */
+            get: function () {
+                if (!this._texture) {
+                    return false;
+                }
+                return this._texture.is3D;
+            },
+            set: function (value) {
+                if (!this._texture) {
+                    return;
+                }
+                this._texture.is3D = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(BaseTexture.prototype, "isRGBD", {
             /**
              * Gets whether or not the texture contains RGBD data.
@@ -32086,7 +32177,6 @@ var BABYLON;
             if (!scene) {
                 return;
             }
-            this._samplingMode = samplingMode;
             scene.getEngine().updateTextureSamplingMode(samplingMode, this._texture);
         };
         /**
@@ -32379,10 +32469,10 @@ var BABYLON;
         ], BaseTexture.prototype, "anisotropicFilteringLevel", void 0);
         __decorate([
             BABYLON.serialize()
-        ], BaseTexture.prototype, "isCube", void 0);
+        ], BaseTexture.prototype, "isCube", null);
         __decorate([
             BABYLON.serialize()
-        ], BaseTexture.prototype, "is3D", void 0);
+        ], BaseTexture.prototype, "is3D", null);
         __decorate([
             BABYLON.serialize()
         ], BaseTexture.prototype, "gammaSpace", void 0);
@@ -32493,6 +32583,8 @@ var BABYLON;
              * Defines the center of rotation (W)
              */
             _this.wRotationCenter = 0.5;
+            /** @hidden */
+            _this._initialSamplingMode = Texture.BILINEAR_SAMPLINGMODE;
             /**
              * Observable triggered once the texture has been loaded.
              */
@@ -32502,7 +32594,7 @@ var BABYLON;
             _this.url = url;
             _this._noMipmap = noMipmap;
             _this._invertY = invertY;
-            _this._samplingMode = samplingMode;
+            _this._initialSamplingMode = samplingMode;
             _this._buffer = buffer;
             _this._deleteBuffer = deleteBuffer;
             if (format) {
@@ -32535,7 +32627,7 @@ var BABYLON;
             _this._texture = _this._getFromCache(_this.url, noMipmap, samplingMode);
             if (!_this._texture) {
                 if (!scene.useDelayedTextureLoading) {
-                    _this._texture = scene.getEngine().createTexture(_this.url, noMipmap, invertY, scene, _this._samplingMode, load, onError, _this._buffer, undefined, _this._format);
+                    _this._texture = scene.getEngine().createTexture(_this.url, noMipmap, invertY, scene, samplingMode, load, onError, _this._buffer, undefined, _this._format);
                     if (deleteBuffer) {
                         delete _this._buffer;
                     }
@@ -32585,7 +32677,10 @@ var BABYLON;
              * Get the current sampling mode associated with the texture.
              */
             get: function () {
-                return this._samplingMode;
+                if (!this._texture) {
+                    return this._initialSamplingMode;
+                }
+                return this._texture.samplingMode;
             },
             enumerable: true,
             configurable: true
@@ -32633,9 +32728,9 @@ var BABYLON;
                 return;
             }
             this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
-            this._texture = this._getFromCache(this.url, this._noMipmap, this._samplingMode);
+            this._texture = this._getFromCache(this.url, this._noMipmap, this.samplingMode);
             if (!this._texture) {
-                this._texture = scene.getEngine().createTexture(this.url, this._noMipmap, this._invertY, scene, this._samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer, null, this._format);
+                this._texture = scene.getEngine().createTexture(this.url, this._noMipmap, this._invertY, scene, this.samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer, null, this._format);
                 if (this._deleteBuffer) {
                     delete this._buffer;
                 }
@@ -32774,7 +32869,7 @@ var BABYLON;
         Texture.prototype.clone = function () {
             var _this = this;
             return BABYLON.SerializationHelper.Clone(function () {
-                return new Texture(_this._texture ? _this._texture.url : null, _this.getScene(), _this._noMipmap, _this._invertY, _this._samplingMode);
+                return new Texture(_this._texture ? _this._texture.url : null, _this.getScene(), _this._noMipmap, _this._invertY, _this.samplingMode);
             }, this);
         };
         /**
@@ -32880,7 +32975,7 @@ var BABYLON;
             // Update Sampling Mode
             if (parsedTexture.samplingMode) {
                 var sampling = parsedTexture.samplingMode;
-                if (texture && texture._samplingMode !== sampling) {
+                if (texture && texture.samplingMode !== sampling) {
                     texture.updateSamplingMode(sampling);
                 }
             }
@@ -33137,7 +33232,9 @@ var BABYLON;
                 // Deep copy
                 BABYLON.Tools.DeepCopy(source, _this, ["name", "material", "skeleton", "instances", "parent", "uniqueId",
                     "source", "metadata", "hasLODLevels", "geometry", "isBlocked", "areNormalsFrozen",
-                    "onBeforeDrawObservable", "onBeforeRenderObservable", "onAfterRenderObservable", "onBeforeDraw"
+                    "onBeforeDrawObservable", "onBeforeRenderObservable", "onAfterRenderObservable", "onBeforeDraw",
+                    "onAfterWorldMatrixUpdateObservable", "onCollideObservable", "onCollisionPositionChangeObservable", "onRebuildObservable",
+                    "onDisposeObservable"
                 ], ["_poseMatrix"]);
                 // Source mesh
                 _this._source = source;
@@ -41590,7 +41687,15 @@ var BABYLON;
                 this.setIndices(indices, null, true);
             }
             else {
+                var needToUpdateSubMeshes = indices.length !== this._indices.length;
+                this._indices = indices;
                 this._engine.updateDynamicIndexBuffer(this._indexBuffer, indices, offset);
+                if (needToUpdateSubMeshes) {
+                    for (var _i = 0, _a = this._meshes; _i < _a.length; _i++) {
+                        var mesh = _a[_i];
+                        mesh._createGlobalSubMesh(true);
+                    }
+                }
             }
         };
         /**
@@ -41614,10 +41719,9 @@ var BABYLON;
             if (totalVertices != undefined) { // including null and undefined
                 this._totalVertices = totalVertices;
             }
-            var meshes = this._meshes;
-            var numOfMeshes = meshes.length;
-            for (var index = 0; index < numOfMeshes; index++) {
-                meshes[index]._createGlobalSubMesh(true);
+            for (var _i = 0, _a = this._meshes; _i < _a.length; _i++) {
+                var mesh = _a[_i];
+                mesh._createGlobalSubMesh(true);
             }
             this.notifyUpdate();
         };
@@ -41923,17 +42027,19 @@ var BABYLON;
             for (kind in this._vertexBuffers) {
                 // using slice() to make a copy of the array and not just reference it
                 var data = this.getVerticesData(kind);
-                if (data instanceof Float32Array) {
-                    vertexData.set(new Float32Array(data), kind);
-                }
-                else {
-                    vertexData.set(data.slice(0), kind);
-                }
-                if (!stopChecking) {
-                    var vb = this.getVertexBuffer(kind);
-                    if (vb) {
-                        updatable = vb.isUpdatable();
-                        stopChecking = !updatable;
+                if (data) {
+                    if (data instanceof Float32Array) {
+                        vertexData.set(new Float32Array(data), kind);
+                    }
+                    else {
+                        vertexData.set(data.slice(0), kind);
+                    }
+                    if (!stopChecking) {
+                        var vb = this.getVertexBuffer(kind);
+                        if (vb) {
+                            updatable = vb.isUpdatable();
+                            stopChecking = !updatable;
+                        }
                     }
                 }
             }
@@ -45272,10 +45378,10 @@ var BABYLON;
         };
         /**
          * Creates a standard material from parsed material data
-         * @param source defines the JSON represnetation of the material
+         * @param source defines the JSON representation of the material
          * @param scene defines the hosting scene
          * @param rootUrl defines the root URL to use to load textures and relative dependencies
-         * @returns a new material
+         * @returns a new standard material
          */
         StandardMaterial.Parse = function (source, scene, rootUrl) {
             return BABYLON.SerializationHelper.Parse(function () { return new StandardMaterial(source.name, scene); }, source, scene, rootUrl);
@@ -67084,7 +67190,7 @@ var BABYLON;
          */
         function DebugLayer(scene) {
             var _this = this;
-            this.BJSINSPECTOR = typeof INSPECTOR !== 'undefined' ? INSPECTOR : undefined;
+            this.BJSINSPECTOR = this._getGlobalInspector();
             /**
              * Observable triggered when a property is changed through the inspector.
              */
@@ -67103,9 +67209,21 @@ var BABYLON;
                 return;
             }
             var userOptions = __assign({ overlay: false, showExplorer: true, showInspector: true, embedMode: false, handleResize: true, enablePopup: true }, config);
-            this.BJSINSPECTOR = this.BJSINSPECTOR || typeof INSPECTOR !== 'undefined' ? INSPECTOR : undefined;
+            this.BJSINSPECTOR = this.BJSINSPECTOR || this._getGlobalInspector();
             this.BJSINSPECTOR.Inspector.Show(this._scene, userOptions);
         };
+        /** Get the inspector from bundle or global */
+        DebugLayer.prototype._getGlobalInspector = function () {
+            // UMD Global name detection from Webpack Bundle UMD Name.
+            if (typeof INSPECTOR !== 'undefined') {
+                return INSPECTOR;
+            }
+            // In case of module let s check the global emitted from the Inspector entry point.
+            if (BABYLON && BABYLON.Inspector) {
+                return BABYLON;
+            }
+            return undefined;
+        };
         /**
          * Get if the inspector is visible or not.
          * @returns true if visible otherwise, false
@@ -70173,7 +70291,7 @@ var BABYLON;
     var MeshBuilder = /** @class */ (function () {
         function MeshBuilder() {
         }
-        MeshBuilder.updateSideOrientation = function (orientation) {
+        MeshBuilder._UpdateSideOrientation = function (orientation) {
             if (orientation == BABYLON.Mesh.DOUBLESIDE) {
                 return BABYLON.Mesh.DOUBLESIDE;
             }
@@ -70200,7 +70318,7 @@ var BABYLON;
         MeshBuilder.CreateBox = function (name, options, scene) {
             if (scene === void 0) { scene = null; }
             var box = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             box._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateBox(options);
             vertexData.applyToMesh(box, options.updatable);
@@ -70224,7 +70342,7 @@ var BABYLON;
          */
         MeshBuilder.CreateSphere = function (name, options, scene) {
             var sphere = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             sphere._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateSphere(options);
             vertexData.applyToMesh(sphere, options.updatable);
@@ -70247,7 +70365,7 @@ var BABYLON;
         MeshBuilder.CreateDisc = function (name, options, scene) {
             if (scene === void 0) { scene = null; }
             var disc = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             disc._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateDisc(options);
             vertexData.applyToMesh(disc, options.updatable);
@@ -70270,7 +70388,7 @@ var BABYLON;
          */
         MeshBuilder.CreateIcoSphere = function (name, options, scene) {
             var sphere = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             sphere._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateIcoSphere(options);
             vertexData.applyToMesh(sphere, options.updatable);
@@ -70304,7 +70422,7 @@ var BABYLON;
             var pathArray = options.pathArray;
             var closeArray = options.closeArray;
             var closePath = options.closePath;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var instance = options.instance;
             var updatable = options.updatable;
             if (instance) { // existing ribbon instance update
@@ -70442,7 +70560,7 @@ var BABYLON;
          */
         MeshBuilder.CreateCylinder = function (name, options, scene) {
             var cylinder = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             cylinder._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateCylinder(options);
             vertexData.applyToMesh(cylinder, options.updatable);
@@ -70464,7 +70582,7 @@ var BABYLON;
          */
         MeshBuilder.CreateTorus = function (name, options, scene) {
             var torus = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             torus._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateTorus(options);
             vertexData.applyToMesh(torus, options.updatable);
@@ -70487,7 +70605,7 @@ var BABYLON;
          */
         MeshBuilder.CreateTorusKnot = function (name, options, scene) {
             var torusKnot = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             torusKnot._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateTorusKnot(options);
             vertexData.applyToMesh(torusKnot, options.updatable);
@@ -70682,7 +70800,7 @@ var BABYLON;
             var rotation = options.rotation || 0;
             var cap = (options.cap === 0) ? 0 : options.cap || BABYLON.Mesh.NO_CAP;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var instance = options.instance || null;
             var invertUV = options.invertUV || false;
             return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, scale, rotation, null, null, false, false, cap, false, scene, updatable ? true : false, sideOrientation, instance, invertUV, options.frontUVs || null, options.backUVs || null);
@@ -70722,7 +70840,7 @@ var BABYLON;
             var ribbonClosePath = options.ribbonClosePath || false;
             var cap = (options.cap === 0) ? 0 : options.cap || BABYLON.Mesh.NO_CAP;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var instance = options.instance;
             var invertUV = options.invertUV || false;
             return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, cap, true, scene, updatable ? true : false, sideOrientation, instance || null, invertUV, options.frontUVs || null, options.backUVs || null);
@@ -70755,7 +70873,7 @@ var BABYLON;
             var tessellation = options.tessellation || 64;
             var clip = options.clip || 0;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var cap = options.cap || BABYLON.Mesh.NO_CAP;
             var pi2 = Math.PI * 2;
             var paths = new Array();
@@ -70801,7 +70919,7 @@ var BABYLON;
          */
         MeshBuilder.CreatePlane = function (name, options, scene) {
             var plane = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             plane._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreatePlane(options);
             vertexData.applyToMesh(plane, options.updatable);
@@ -70945,7 +71063,7 @@ var BABYLON;
          * @returns the polygon mesh
          */
         MeshBuilder.CreatePolygon = function (name, options, scene) {
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var shape = options.shape;
             var holes = options.holes || [];
             var depth = options.depth || 0;
@@ -71021,7 +71139,7 @@ var BABYLON;
             var cap = options.cap || BABYLON.Mesh.NO_CAP;
             var invertUV = options.invertUV || false;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             options.arc = options.arc && (options.arc <= 0.0 || options.arc > 1.0) ? 1.0 : options.arc || 1.0;
             // tube geometry
             var tubePathArray = function (path, path3D, circlePaths, radius, tessellation, radiusFunction, cap, arc) {
@@ -71132,7 +71250,7 @@ var BABYLON;
          */
         MeshBuilder.CreatePolyhedron = function (name, options, scene) {
             var polyhedron = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             polyhedron._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreatePolyhedron(options);
             vertexData.applyToMesh(polyhedron, options.updatable);
@@ -75651,7 +75769,7 @@ var BABYLON;
             this._canvas.width = textureSize.width;
             this._canvas.height = textureSize.height;
             this.releaseInternalTexture();
-            this._texture = this._engine.createDynamicTexture(textureSize.width, textureSize.height, this._generateMipMaps, this._samplingMode);
+            this._texture = this._engine.createDynamicTexture(textureSize.width, textureSize.height, this._generateMipMaps, this.samplingMode);
         };
         /**
          * Scales the texture
@@ -75831,7 +75949,7 @@ var BABYLON;
                     _this.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
                     _this._generateMipMaps = false;
                 }
-                _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this._samplingMode);
+                _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this.samplingMode);
                 if (!_this.video.autoplay && !_this._settings.poster) {
                     var oldHandler_1 = _this.video.onplaying;
                     var error_1 = false;
@@ -75899,7 +76017,7 @@ var BABYLON;
             };
             _this._engine = _this.getScene().getEngine();
             _this._generateMipMaps = generateMipMaps;
-            _this._samplingMode = samplingMode;
+            _this._initialSamplingMode = samplingMode;
             _this.autoUpdateTexture = settings.autoUpdateTexture;
             _this.name = name || _this._getName(src);
             _this.video = _this._getVideo(src);
@@ -102270,23 +102388,23 @@ var BABYLON;
                 BABYLON.Tools.Error("texture missing KTX identifier");
                 return;
             }
-            // load the reset of the header in native 32 bit int
-            var header = new Int32Array(this.arrayBuffer, 12, 13);
-            // determine of the remaining header values are recorded in the opposite endianness & require conversion
-            var oppositeEndianess = header[0] === 0x01020304;
-            // read all the header elements in order they exist in the file, without modification (sans endainness)
-            this.glType = oppositeEndianess ? this.switchEndianness(header[1]) : header[1]; // must be 0 for compressed textures
-            this.glTypeSize = oppositeEndianess ? this.switchEndianness(header[2]) : header[2]; // must be 1 for compressed textures
-            this.glFormat = oppositeEndianess ? this.switchEndianness(header[3]) : header[3]; // must be 0 for compressed textures
-            this.glInternalFormat = oppositeEndianess ? this.switchEndianness(header[4]) : header[4]; // the value of arg passed to gl.compressedTexImage2D(,,x,,,,)
-            this.glBaseInternalFormat = oppositeEndianess ? this.switchEndianness(header[5]) : header[5]; // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only)
-            this.pixelWidth = oppositeEndianess ? this.switchEndianness(header[6]) : header[6]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,)
-            this.pixelHeight = oppositeEndianess ? this.switchEndianness(header[7]) : header[7]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,)
-            this.pixelDepth = oppositeEndianess ? this.switchEndianness(header[8]) : header[8]; // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,)
-            this.numberOfArrayElements = oppositeEndianess ? this.switchEndianness(header[9]) : header[9]; // used for texture arrays
-            this.numberOfFaces = oppositeEndianess ? this.switchEndianness(header[10]) : header[10]; // used for cubemap textures, should either be 1 or 6
-            this.numberOfMipmapLevels = oppositeEndianess ? this.switchEndianness(header[11]) : header[11]; // number of levels; disregard possibility of 0 for compressed textures
-            this.bytesOfKeyValueData = oppositeEndianess ? this.switchEndianness(header[12]) : header[12]; // the amount of space after the header for meta-data
+            // load the reset of the header in native 32 bit uint
+            var dataSize = Uint32Array.BYTES_PER_ELEMENT;
+            var headerDataView = new DataView(this.arrayBuffer, 12, 13 * dataSize);
+            var endianness = headerDataView.getUint32(0, true);
+            var littleEndian = endianness === 0x04030201;
+            this.glType = headerDataView.getUint32(1 * dataSize, littleEndian); // must be 0 for compressed textures
+            this.glTypeSize = headerDataView.getUint32(2 * dataSize, littleEndian); // must be 1 for compressed textures
+            this.glFormat = headerDataView.getUint32(3 * dataSize, littleEndian); // must be 0 for compressed textures
+            this.glInternalFormat = headerDataView.getUint32(4 * dataSize, littleEndian); // the value of arg passed to gl.compressedTexImage2D(,,x,,,,)
+            this.glBaseInternalFormat = headerDataView.getUint32(5 * dataSize, littleEndian); // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only)
+            this.pixelWidth = headerDataView.getUint32(6 * dataSize, littleEndian); // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,)
+            this.pixelHeight = headerDataView.getUint32(7 * dataSize, littleEndian); // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,)
+            this.pixelDepth = headerDataView.getUint32(8 * dataSize, littleEndian); // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,)
+            this.numberOfArrayElements = headerDataView.getUint32(9 * dataSize, littleEndian); // used for texture arrays
+            this.numberOfFaces = headerDataView.getUint32(10 * dataSize, littleEndian); // used for cubemap textures, should either be 1 or 6
+            this.numberOfMipmapLevels = headerDataView.getUint32(11 * dataSize, littleEndian); // number of levels; disregard possibility of 0 for compressed textures
+            this.bytesOfKeyValueData = headerDataView.getUint32(12 * dataSize, littleEndian); // the amount of space after the header for meta-data
             // Make sure we have a compressed type.  Not only reduces work, but probably better to let dev know they are not compressing.
             if (this.glType !== 0) {
                 BABYLON.Tools.Error("only compressed formats currently supported");
@@ -102312,19 +102430,6 @@ var BABYLON;
             // would need to make this more elaborate & adjust checks above to support more than one load type
             this.loadType = KhronosTextureContainer.COMPRESSED_2D;
         }
-        //
-        /**
-         * Revert the endianness of a value.
-         * Not as fast hardware based, but will probably never need to use
-         * @param val defines the value to convert
-         * @returns the new value
-         */
-        KhronosTextureContainer.prototype.switchEndianness = function (val) {
-            return ((val & 0xFF) << 24)
-                | ((val & 0xFF00) << 8)
-                | ((val >> 8) & 0xFF00)
-                | ((val >> 24) & 0xFF);
-        };
         /**
          * Uploads KTX content to a Babylon Texture.
          * It is assumed that the texture has already been created & is currently bound
@@ -117236,7 +117341,7 @@ var BABYLON;
             if (useBilinearMode === void 0) { useBilinearMode = true; }
             var scene = texture.getScene();
             var engine = scene.getEngine();
-            var rtt = new BABYLON.RenderTargetTexture('resized' + texture.name, { width: width, height: height }, scene, !texture.noMipmap, true, texture._texture.type, false, texture._samplingMode, false);
+            var rtt = new BABYLON.RenderTargetTexture('resized' + texture.name, { width: width, height: height }, scene, !texture.noMipmap, true, texture._texture.type, false, texture.samplingMode, false);
             rtt.wrapU = texture.wrapU;
             rtt.wrapV = texture.wrapV;
             rtt.uOffset = texture.uOffset;

+ 226 - 121
dist/preview release/babylon.no-module.max.js

@@ -12941,7 +12941,7 @@ var BABYLON;
              * Returns the current version of the framework
              */
             get: function () {
-                return "4.0.0-alpha.11";
+                return "4.0.0-alpha.14";
             },
             enumerable: true,
             configurable: true
@@ -15790,8 +15790,7 @@ var BABYLON;
                         customFallback = true;
                         excludeLoaders.push(loader);
                         BABYLON.Tools.Warn(loader.constructor.name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
-                        _this.createTexture(urlArg, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture, undefined, undefined, excludeLoaders);
-                        return;
+                        _this.createTexture(urlArg, noMipmap, texture.invertY, scene, samplingMode, null, null, buffer, texture, undefined, undefined, excludeLoaders);
                     }
                 }
                 if (!customFallback) {
@@ -15799,8 +15798,7 @@ var BABYLON;
                         texture.onLoadedObservable.remove(onLoadObserver);
                     }
                     if (BABYLON.Tools.UseFallbackTexture) {
-                        _this.createTexture(BABYLON.Tools.fallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture);
-                        return;
+                        _this.createTexture(BABYLON.Tools.fallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, null, buffer, texture);
                     }
                 }
                 if (onError) {
@@ -19539,8 +19537,25 @@ var BABYLON;
          * @returns true if there is an intersection
          */
         BoundingSphere.prototype.isInFrustum = function (frustumPlanes) {
+            var center = this.centerWorld;
+            var radius = this.radiusWorld;
+            for (var i = 0; i < 6; i++) {
+                if (frustumPlanes[i].dotCoordinate(center) <= -radius) {
+                    return false;
+                }
+            }
+            return true;
+        };
+        /**
+         * Tests if the bounding sphere center is in between the frustum planes.
+         * Used for optimistic fast inclusion.
+         * @param frustumPlanes defines the frustum planes to test
+         * @returns true if the sphere center is in between the frustum planes
+         */
+        BoundingSphere.prototype.isCenterInFrustum = function (frustumPlanes) {
+            var center = this.centerWorld;
             for (var i = 0; i < 6; i++) {
-                if (frustumPlanes[i].dotCoordinate(this.centerWorld) <= -this.radiusWorld) {
+                if (frustumPlanes[i].dotCoordinate(center) < 0) {
                     return false;
                 }
             }
@@ -19977,15 +19992,22 @@ var BABYLON;
         /**
          * Returns `true` if the bounding info is within the frustum defined by the passed array of planes.
          * @param frustumPlanes defines the frustum to test
-         * @param strategy defines the strategy to use for the culling (default is BABYLON.Scene.CULLINGSTRATEGY_STANDARD)
+         * @param strategy defines the strategy to use for the culling (default is BABYLON.AbstractMesh.CULLINGSTRATEGY_STANDARD)
          * @returns true if the bounding info is in the frustum planes
          */
         BoundingInfo.prototype.isInFrustum = function (frustumPlanes, strategy) {
             if (strategy === void 0) { strategy = BABYLON.AbstractMesh.CULLINGSTRATEGY_STANDARD; }
+            var inclusionTest = (strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION || strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY);
+            if (inclusionTest) {
+                if (this.boundingSphere.isCenterInFrustum(frustumPlanes)) {
+                    return true;
+                }
+            }
             if (!this.boundingSphere.isInFrustum(frustumPlanes)) {
                 return false;
             }
-            if (strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY) {
+            var bSphereOnlyTest = (strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY || strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY);
+            if (bSphereOnlyTest) {
                 return true;
             }
             return this.boundingBox.isInFrustum(frustumPlanes);
@@ -21240,7 +21262,16 @@ var BABYLON;
             if (scene === void 0) { scene = null; }
             var _this = _super.call(this, name, scene, false) || this;
             _this._facetData = new _FacetDataStorage();
-            /** Gets ot sets the culling strategy to use to find visible meshes */
+            /**
+             * The culling strategy to use to check whether the mesh must be rendered or not.
+             * This value can be changed at any time and will be used on the next render mesh selection.
+             * The possible values are :
+             * - AbstractMesh.CULLINGSTRATEGY_STANDARD
+             * - AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY
+             * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION
+             * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY
+             * Please read each static variable documentation to get details about the culling process.
+             * */
             _this.cullingStrategy = AbstractMesh.CULLINGSTRATEGY_STANDARD;
             // Events
             /**
@@ -23041,10 +23072,40 @@ var BABYLON;
         AbstractMesh.OCCLUSION_ALGORITHM_TYPE_ACCURATE = 0;
         /** Use a conservative occlusion algorithm */
         AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE = 1;
-        /** Default culling strategy with bounding box and bounding sphere and then frustum culling */
+        /** Default culling strategy : this is an exclusion test and it's the more accurate.
+         *  Test order :
+         *  Is the bounding sphere outside the frustum ?
+         *  If not, are the bounding box vertices outside the frustum ?
+         *  It not, then the cullable object is in the frustum.
+         */
         AbstractMesh.CULLINGSTRATEGY_STANDARD = 0;
-        /** Culling strategy with bounding sphere only and then frustum culling */
+        /** Culling strategy : Bounding Sphere Only.
+         *  This is an exclusion test. It's faster than the standard strategy because the bounding box is not tested.
+         *  It's also less accurate than the standard because some not visible objects can still be selected.
+         *  Test : is the bounding sphere outside the frustum ?
+         *  If not, then the cullable object is in the frustum.
+         */
         AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY = 1;
+        /** Culling strategy : Optimistic Inclusion.
+         *  This in an inclusion test first, then the standard exclusion test.
+         *  This can be faster when a cullable object is expected to be almost always in the camera frustum.
+         *  This could also be a little slower than the standard test when the tested object center is not the frustum but one of its bounding box vertex is still inside.
+         *  Anyway, it's as accurate as the standard strategy.
+         *  Test :
+         *  Is the cullable object bounding sphere center in the frustum ?
+         *  If not, apply the default culling strategy.
+         */
+        AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION = 2;
+        /** Culling strategy : Optimistic Inclusion then Bounding Sphere Only.
+         *  This in an inclusion test first, then the bounding sphere only exclusion test.
+         *  This can be the fastest test when a cullable object is expected to be almost always in the camera frustum.
+         *  This could also be a little slower than the BoundingSphereOnly strategy when the tested object center is not in the frustum but its bounding sphere still intersects it.
+         *  It's less accurate than the standard strategy and as accurate as the BoundingSphereOnly strategy.
+         *  Test :
+         *  Is the cullable object bounding sphere center in the frustum ?
+         *  If not, apply the Bounding Sphere Only strategy. No Bounding Box is tested here.
+         */
+        AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY = 3;
         return AbstractMesh;
     }(BABYLON.TransformNode));
     BABYLON.AbstractMesh = AbstractMesh;
@@ -26339,7 +26400,7 @@ var BABYLON;
             /**
              * an optional map from Geometry Id to Geometry index in the 'geometries' array
              */
-            _this.geometriesById = null;
+            _this.geometriesByUniqueId = null;
             _this._defaultMeshCandidates = {
                 data: [],
                 length: 0
@@ -26379,10 +26440,10 @@ var BABYLON;
                 _this._imageProcessingConfiguration = new BABYLON.ImageProcessingConfiguration();
             }
             _this.setDefaultCandidateProviders();
-            if (options && options.useGeometryIdsMap === true) {
-                _this.geometriesById = {};
+            if (options && options.useGeometryUniqueIdsMap === true) {
+                _this.geometriesByUniqueId = {};
             }
-            _this.useMaterialMeshMap = options && options.useGeometryIdsMap || false;
+            _this.useMaterialMeshMap = options && options.useGeometryUniqueIdsMap || false;
             _this.useClonedMeshhMap = options && options.useClonedMeshhMap || false;
             _this._engine.onNewSceneAddedObservable.notifyObservers(_this);
             return _this;
@@ -28624,8 +28685,8 @@ var BABYLON;
          * @param newGeometry The geometry to add
          */
         Scene.prototype.addGeometry = function (newGeometry) {
-            if (this.geometriesById) {
-                this.geometriesById[newGeometry.id] = this.geometries.length;
+            if (this.geometriesByUniqueId) {
+                this.geometriesByUniqueId[newGeometry.uniqueId] = this.geometries.length;
             }
             this.geometries.push(newGeometry);
         };
@@ -28857,29 +28918,29 @@ var BABYLON;
          * @return the geometry or null if none found.
          */
         Scene.prototype.getGeometryByID = function (id) {
-            if (this.geometriesById) {
-                var index_1 = this.geometriesById[id];
+            for (var index = 0; index < this.geometries.length; index++) {
+                if (this.geometries[index].id === id) {
+                    return this.geometries[index];
+                }
+            }
+            return null;
+        };
+        Scene.prototype._getGeometryByUniqueID = function (uniqueId) {
+            if (this.geometriesByUniqueId) {
+                var index_1 = this.geometriesByUniqueId[uniqueId];
                 if (index_1 !== undefined) {
                     return this.geometries[index_1];
                 }
             }
             else {
                 for (var index = 0; index < this.geometries.length; index++) {
-                    if (this.geometries[index].id === id) {
+                    if (this.geometries[index].uniqueId === uniqueId) {
                         return this.geometries[index];
                     }
                 }
             }
             return null;
         };
-        Scene.prototype._getGeometryByUniqueID = function (id) {
-            for (var index = 0; index < this.geometries.length; index++) {
-                if (this.geometries[index].uniqueId === id) {
-                    return this.geometries[index];
-                }
-            }
-            return null;
-        };
         /**
          * Add a new geometry to this scene
          * @param geometry defines the geometry to be added to the scene.
@@ -28905,8 +28966,8 @@ var BABYLON;
          */
         Scene.prototype.removeGeometry = function (geometry) {
             var index;
-            if (this.geometriesById) {
-                index = this.geometriesById[geometry.id];
+            if (this.geometriesByUniqueId) {
+                index = this.geometriesByUniqueId[geometry.uniqueId];
                 if (index === undefined) {
                     return false;
                 }
@@ -28920,9 +28981,9 @@ var BABYLON;
             if (index !== this.geometries.length - 1) {
                 var lastGeometry = this.geometries[this.geometries.length - 1];
                 this.geometries[index] = lastGeometry;
-                if (this.geometriesById) {
-                    this.geometriesById[lastGeometry.id] = index;
-                    this.geometriesById[geometry.id] = undefined;
+                if (this.geometriesByUniqueId) {
+                    this.geometriesByUniqueId[lastGeometry.uniqueId] = index;
+                    this.geometriesByUniqueId[geometry.uniqueId] = undefined;
                 }
             }
             this.geometries.pop();
@@ -31735,14 +31796,6 @@ var BABYLON;
              */
             this.anisotropicFilteringLevel = BaseTexture.DEFAULT_ANISOTROPIC_FILTERING_LEVEL;
             /**
-             * Define if the texture is a cube texture or if false a 2d texture.
-             */
-            this.isCube = false;
-            /**
-             * Define if the texture is a 3d texture (webgl 2) or if false a 2d texture.
-             */
-            this.is3D = false;
-            /**
              * Define if the texture contains data in gamma space (most of the png/jpg aside bump).
              * HDR texture are usually stored in linear space.
              * This only impacts the PBR and Background materials
@@ -31831,6 +31884,44 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(BaseTexture.prototype, "isCube", {
+            /**
+             * Define if the texture is a cube texture or if false a 2d texture.
+             */
+            get: function () {
+                if (!this._texture) {
+                    return false;
+                }
+                return this._texture.isCube;
+            },
+            set: function (value) {
+                if (!this._texture) {
+                    return;
+                }
+                this._texture.isCube = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(BaseTexture.prototype, "is3D", {
+            /**
+             * Define if the texture is a 3d texture (webgl 2) or if false a 2d texture.
+             */
+            get: function () {
+                if (!this._texture) {
+                    return false;
+                }
+                return this._texture.is3D;
+            },
+            set: function (value) {
+                if (!this._texture) {
+                    return;
+                }
+                this._texture.is3D = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(BaseTexture.prototype, "isRGBD", {
             /**
              * Gets whether or not the texture contains RGBD data.
@@ -32053,7 +32144,6 @@ var BABYLON;
             if (!scene) {
                 return;
             }
-            this._samplingMode = samplingMode;
             scene.getEngine().updateTextureSamplingMode(samplingMode, this._texture);
         };
         /**
@@ -32346,10 +32436,10 @@ var BABYLON;
         ], BaseTexture.prototype, "anisotropicFilteringLevel", void 0);
         __decorate([
             BABYLON.serialize()
-        ], BaseTexture.prototype, "isCube", void 0);
+        ], BaseTexture.prototype, "isCube", null);
         __decorate([
             BABYLON.serialize()
-        ], BaseTexture.prototype, "is3D", void 0);
+        ], BaseTexture.prototype, "is3D", null);
         __decorate([
             BABYLON.serialize()
         ], BaseTexture.prototype, "gammaSpace", void 0);
@@ -32460,6 +32550,8 @@ var BABYLON;
              * Defines the center of rotation (W)
              */
             _this.wRotationCenter = 0.5;
+            /** @hidden */
+            _this._initialSamplingMode = Texture.BILINEAR_SAMPLINGMODE;
             /**
              * Observable triggered once the texture has been loaded.
              */
@@ -32469,7 +32561,7 @@ var BABYLON;
             _this.url = url;
             _this._noMipmap = noMipmap;
             _this._invertY = invertY;
-            _this._samplingMode = samplingMode;
+            _this._initialSamplingMode = samplingMode;
             _this._buffer = buffer;
             _this._deleteBuffer = deleteBuffer;
             if (format) {
@@ -32502,7 +32594,7 @@ var BABYLON;
             _this._texture = _this._getFromCache(_this.url, noMipmap, samplingMode);
             if (!_this._texture) {
                 if (!scene.useDelayedTextureLoading) {
-                    _this._texture = scene.getEngine().createTexture(_this.url, noMipmap, invertY, scene, _this._samplingMode, load, onError, _this._buffer, undefined, _this._format);
+                    _this._texture = scene.getEngine().createTexture(_this.url, noMipmap, invertY, scene, samplingMode, load, onError, _this._buffer, undefined, _this._format);
                     if (deleteBuffer) {
                         delete _this._buffer;
                     }
@@ -32552,7 +32644,10 @@ var BABYLON;
              * Get the current sampling mode associated with the texture.
              */
             get: function () {
-                return this._samplingMode;
+                if (!this._texture) {
+                    return this._initialSamplingMode;
+                }
+                return this._texture.samplingMode;
             },
             enumerable: true,
             configurable: true
@@ -32600,9 +32695,9 @@ var BABYLON;
                 return;
             }
             this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
-            this._texture = this._getFromCache(this.url, this._noMipmap, this._samplingMode);
+            this._texture = this._getFromCache(this.url, this._noMipmap, this.samplingMode);
             if (!this._texture) {
-                this._texture = scene.getEngine().createTexture(this.url, this._noMipmap, this._invertY, scene, this._samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer, null, this._format);
+                this._texture = scene.getEngine().createTexture(this.url, this._noMipmap, this._invertY, scene, this.samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer, null, this._format);
                 if (this._deleteBuffer) {
                     delete this._buffer;
                 }
@@ -32741,7 +32836,7 @@ var BABYLON;
         Texture.prototype.clone = function () {
             var _this = this;
             return BABYLON.SerializationHelper.Clone(function () {
-                return new Texture(_this._texture ? _this._texture.url : null, _this.getScene(), _this._noMipmap, _this._invertY, _this._samplingMode);
+                return new Texture(_this._texture ? _this._texture.url : null, _this.getScene(), _this._noMipmap, _this._invertY, _this.samplingMode);
             }, this);
         };
         /**
@@ -32847,7 +32942,7 @@ var BABYLON;
             // Update Sampling Mode
             if (parsedTexture.samplingMode) {
                 var sampling = parsedTexture.samplingMode;
-                if (texture && texture._samplingMode !== sampling) {
+                if (texture && texture.samplingMode !== sampling) {
                     texture.updateSamplingMode(sampling);
                 }
             }
@@ -33104,7 +33199,9 @@ var BABYLON;
                 // Deep copy
                 BABYLON.Tools.DeepCopy(source, _this, ["name", "material", "skeleton", "instances", "parent", "uniqueId",
                     "source", "metadata", "hasLODLevels", "geometry", "isBlocked", "areNormalsFrozen",
-                    "onBeforeDrawObservable", "onBeforeRenderObservable", "onAfterRenderObservable", "onBeforeDraw"
+                    "onBeforeDrawObservable", "onBeforeRenderObservable", "onAfterRenderObservable", "onBeforeDraw",
+                    "onAfterWorldMatrixUpdateObservable", "onCollideObservable", "onCollisionPositionChangeObservable", "onRebuildObservable",
+                    "onDisposeObservable"
                 ], ["_poseMatrix"]);
                 // Source mesh
                 _this._source = source;
@@ -41557,7 +41654,15 @@ var BABYLON;
                 this.setIndices(indices, null, true);
             }
             else {
+                var needToUpdateSubMeshes = indices.length !== this._indices.length;
+                this._indices = indices;
                 this._engine.updateDynamicIndexBuffer(this._indexBuffer, indices, offset);
+                if (needToUpdateSubMeshes) {
+                    for (var _i = 0, _a = this._meshes; _i < _a.length; _i++) {
+                        var mesh = _a[_i];
+                        mesh._createGlobalSubMesh(true);
+                    }
+                }
             }
         };
         /**
@@ -41581,10 +41686,9 @@ var BABYLON;
             if (totalVertices != undefined) { // including null and undefined
                 this._totalVertices = totalVertices;
             }
-            var meshes = this._meshes;
-            var numOfMeshes = meshes.length;
-            for (var index = 0; index < numOfMeshes; index++) {
-                meshes[index]._createGlobalSubMesh(true);
+            for (var _i = 0, _a = this._meshes; _i < _a.length; _i++) {
+                var mesh = _a[_i];
+                mesh._createGlobalSubMesh(true);
             }
             this.notifyUpdate();
         };
@@ -41890,17 +41994,19 @@ var BABYLON;
             for (kind in this._vertexBuffers) {
                 // using slice() to make a copy of the array and not just reference it
                 var data = this.getVerticesData(kind);
-                if (data instanceof Float32Array) {
-                    vertexData.set(new Float32Array(data), kind);
-                }
-                else {
-                    vertexData.set(data.slice(0), kind);
-                }
-                if (!stopChecking) {
-                    var vb = this.getVertexBuffer(kind);
-                    if (vb) {
-                        updatable = vb.isUpdatable();
-                        stopChecking = !updatable;
+                if (data) {
+                    if (data instanceof Float32Array) {
+                        vertexData.set(new Float32Array(data), kind);
+                    }
+                    else {
+                        vertexData.set(data.slice(0), kind);
+                    }
+                    if (!stopChecking) {
+                        var vb = this.getVertexBuffer(kind);
+                        if (vb) {
+                            updatable = vb.isUpdatable();
+                            stopChecking = !updatable;
+                        }
                     }
                 }
             }
@@ -45239,10 +45345,10 @@ var BABYLON;
         };
         /**
          * Creates a standard material from parsed material data
-         * @param source defines the JSON represnetation of the material
+         * @param source defines the JSON representation of the material
          * @param scene defines the hosting scene
          * @param rootUrl defines the root URL to use to load textures and relative dependencies
-         * @returns a new material
+         * @returns a new standard material
          */
         StandardMaterial.Parse = function (source, scene, rootUrl) {
             return BABYLON.SerializationHelper.Parse(function () { return new StandardMaterial(source.name, scene); }, source, scene, rootUrl);
@@ -67051,7 +67157,7 @@ var BABYLON;
          */
         function DebugLayer(scene) {
             var _this = this;
-            this.BJSINSPECTOR = typeof INSPECTOR !== 'undefined' ? INSPECTOR : undefined;
+            this.BJSINSPECTOR = this._getGlobalInspector();
             /**
              * Observable triggered when a property is changed through the inspector.
              */
@@ -67070,9 +67176,21 @@ var BABYLON;
                 return;
             }
             var userOptions = __assign({ overlay: false, showExplorer: true, showInspector: true, embedMode: false, handleResize: true, enablePopup: true }, config);
-            this.BJSINSPECTOR = this.BJSINSPECTOR || typeof INSPECTOR !== 'undefined' ? INSPECTOR : undefined;
+            this.BJSINSPECTOR = this.BJSINSPECTOR || this._getGlobalInspector();
             this.BJSINSPECTOR.Inspector.Show(this._scene, userOptions);
         };
+        /** Get the inspector from bundle or global */
+        DebugLayer.prototype._getGlobalInspector = function () {
+            // UMD Global name detection from Webpack Bundle UMD Name.
+            if (typeof INSPECTOR !== 'undefined') {
+                return INSPECTOR;
+            }
+            // In case of module let s check the global emitted from the Inspector entry point.
+            if (BABYLON && BABYLON.Inspector) {
+                return BABYLON;
+            }
+            return undefined;
+        };
         /**
          * Get if the inspector is visible or not.
          * @returns true if visible otherwise, false
@@ -70140,7 +70258,7 @@ var BABYLON;
     var MeshBuilder = /** @class */ (function () {
         function MeshBuilder() {
         }
-        MeshBuilder.updateSideOrientation = function (orientation) {
+        MeshBuilder._UpdateSideOrientation = function (orientation) {
             if (orientation == BABYLON.Mesh.DOUBLESIDE) {
                 return BABYLON.Mesh.DOUBLESIDE;
             }
@@ -70167,7 +70285,7 @@ var BABYLON;
         MeshBuilder.CreateBox = function (name, options, scene) {
             if (scene === void 0) { scene = null; }
             var box = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             box._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateBox(options);
             vertexData.applyToMesh(box, options.updatable);
@@ -70191,7 +70309,7 @@ var BABYLON;
          */
         MeshBuilder.CreateSphere = function (name, options, scene) {
             var sphere = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             sphere._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateSphere(options);
             vertexData.applyToMesh(sphere, options.updatable);
@@ -70214,7 +70332,7 @@ var BABYLON;
         MeshBuilder.CreateDisc = function (name, options, scene) {
             if (scene === void 0) { scene = null; }
             var disc = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             disc._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateDisc(options);
             vertexData.applyToMesh(disc, options.updatable);
@@ -70237,7 +70355,7 @@ var BABYLON;
          */
         MeshBuilder.CreateIcoSphere = function (name, options, scene) {
             var sphere = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             sphere._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateIcoSphere(options);
             vertexData.applyToMesh(sphere, options.updatable);
@@ -70271,7 +70389,7 @@ var BABYLON;
             var pathArray = options.pathArray;
             var closeArray = options.closeArray;
             var closePath = options.closePath;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var instance = options.instance;
             var updatable = options.updatable;
             if (instance) { // existing ribbon instance update
@@ -70409,7 +70527,7 @@ var BABYLON;
          */
         MeshBuilder.CreateCylinder = function (name, options, scene) {
             var cylinder = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             cylinder._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateCylinder(options);
             vertexData.applyToMesh(cylinder, options.updatable);
@@ -70431,7 +70549,7 @@ var BABYLON;
          */
         MeshBuilder.CreateTorus = function (name, options, scene) {
             var torus = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             torus._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateTorus(options);
             vertexData.applyToMesh(torus, options.updatable);
@@ -70454,7 +70572,7 @@ var BABYLON;
          */
         MeshBuilder.CreateTorusKnot = function (name, options, scene) {
             var torusKnot = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             torusKnot._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateTorusKnot(options);
             vertexData.applyToMesh(torusKnot, options.updatable);
@@ -70649,7 +70767,7 @@ var BABYLON;
             var rotation = options.rotation || 0;
             var cap = (options.cap === 0) ? 0 : options.cap || BABYLON.Mesh.NO_CAP;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var instance = options.instance || null;
             var invertUV = options.invertUV || false;
             return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, scale, rotation, null, null, false, false, cap, false, scene, updatable ? true : false, sideOrientation, instance, invertUV, options.frontUVs || null, options.backUVs || null);
@@ -70689,7 +70807,7 @@ var BABYLON;
             var ribbonClosePath = options.ribbonClosePath || false;
             var cap = (options.cap === 0) ? 0 : options.cap || BABYLON.Mesh.NO_CAP;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var instance = options.instance;
             var invertUV = options.invertUV || false;
             return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, cap, true, scene, updatable ? true : false, sideOrientation, instance || null, invertUV, options.frontUVs || null, options.backUVs || null);
@@ -70722,7 +70840,7 @@ var BABYLON;
             var tessellation = options.tessellation || 64;
             var clip = options.clip || 0;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var cap = options.cap || BABYLON.Mesh.NO_CAP;
             var pi2 = Math.PI * 2;
             var paths = new Array();
@@ -70768,7 +70886,7 @@ var BABYLON;
          */
         MeshBuilder.CreatePlane = function (name, options, scene) {
             var plane = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             plane._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreatePlane(options);
             vertexData.applyToMesh(plane, options.updatable);
@@ -70912,7 +71030,7 @@ var BABYLON;
          * @returns the polygon mesh
          */
         MeshBuilder.CreatePolygon = function (name, options, scene) {
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var shape = options.shape;
             var holes = options.holes || [];
             var depth = options.depth || 0;
@@ -70988,7 +71106,7 @@ var BABYLON;
             var cap = options.cap || BABYLON.Mesh.NO_CAP;
             var invertUV = options.invertUV || false;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             options.arc = options.arc && (options.arc <= 0.0 || options.arc > 1.0) ? 1.0 : options.arc || 1.0;
             // tube geometry
             var tubePathArray = function (path, path3D, circlePaths, radius, tessellation, radiusFunction, cap, arc) {
@@ -71099,7 +71217,7 @@ var BABYLON;
          */
         MeshBuilder.CreatePolyhedron = function (name, options, scene) {
             var polyhedron = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             polyhedron._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreatePolyhedron(options);
             vertexData.applyToMesh(polyhedron, options.updatable);
@@ -75618,7 +75736,7 @@ var BABYLON;
             this._canvas.width = textureSize.width;
             this._canvas.height = textureSize.height;
             this.releaseInternalTexture();
-            this._texture = this._engine.createDynamicTexture(textureSize.width, textureSize.height, this._generateMipMaps, this._samplingMode);
+            this._texture = this._engine.createDynamicTexture(textureSize.width, textureSize.height, this._generateMipMaps, this.samplingMode);
         };
         /**
          * Scales the texture
@@ -75798,7 +75916,7 @@ var BABYLON;
                     _this.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
                     _this._generateMipMaps = false;
                 }
-                _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this._samplingMode);
+                _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this.samplingMode);
                 if (!_this.video.autoplay && !_this._settings.poster) {
                     var oldHandler_1 = _this.video.onplaying;
                     var error_1 = false;
@@ -75866,7 +75984,7 @@ var BABYLON;
             };
             _this._engine = _this.getScene().getEngine();
             _this._generateMipMaps = generateMipMaps;
-            _this._samplingMode = samplingMode;
+            _this._initialSamplingMode = samplingMode;
             _this.autoUpdateTexture = settings.autoUpdateTexture;
             _this.name = name || _this._getName(src);
             _this.video = _this._getVideo(src);
@@ -102237,23 +102355,23 @@ var BABYLON;
                 BABYLON.Tools.Error("texture missing KTX identifier");
                 return;
             }
-            // load the reset of the header in native 32 bit int
-            var header = new Int32Array(this.arrayBuffer, 12, 13);
-            // determine of the remaining header values are recorded in the opposite endianness & require conversion
-            var oppositeEndianess = header[0] === 0x01020304;
-            // read all the header elements in order they exist in the file, without modification (sans endainness)
-            this.glType = oppositeEndianess ? this.switchEndianness(header[1]) : header[1]; // must be 0 for compressed textures
-            this.glTypeSize = oppositeEndianess ? this.switchEndianness(header[2]) : header[2]; // must be 1 for compressed textures
-            this.glFormat = oppositeEndianess ? this.switchEndianness(header[3]) : header[3]; // must be 0 for compressed textures
-            this.glInternalFormat = oppositeEndianess ? this.switchEndianness(header[4]) : header[4]; // the value of arg passed to gl.compressedTexImage2D(,,x,,,,)
-            this.glBaseInternalFormat = oppositeEndianess ? this.switchEndianness(header[5]) : header[5]; // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only)
-            this.pixelWidth = oppositeEndianess ? this.switchEndianness(header[6]) : header[6]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,)
-            this.pixelHeight = oppositeEndianess ? this.switchEndianness(header[7]) : header[7]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,)
-            this.pixelDepth = oppositeEndianess ? this.switchEndianness(header[8]) : header[8]; // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,)
-            this.numberOfArrayElements = oppositeEndianess ? this.switchEndianness(header[9]) : header[9]; // used for texture arrays
-            this.numberOfFaces = oppositeEndianess ? this.switchEndianness(header[10]) : header[10]; // used for cubemap textures, should either be 1 or 6
-            this.numberOfMipmapLevels = oppositeEndianess ? this.switchEndianness(header[11]) : header[11]; // number of levels; disregard possibility of 0 for compressed textures
-            this.bytesOfKeyValueData = oppositeEndianess ? this.switchEndianness(header[12]) : header[12]; // the amount of space after the header for meta-data
+            // load the reset of the header in native 32 bit uint
+            var dataSize = Uint32Array.BYTES_PER_ELEMENT;
+            var headerDataView = new DataView(this.arrayBuffer, 12, 13 * dataSize);
+            var endianness = headerDataView.getUint32(0, true);
+            var littleEndian = endianness === 0x04030201;
+            this.glType = headerDataView.getUint32(1 * dataSize, littleEndian); // must be 0 for compressed textures
+            this.glTypeSize = headerDataView.getUint32(2 * dataSize, littleEndian); // must be 1 for compressed textures
+            this.glFormat = headerDataView.getUint32(3 * dataSize, littleEndian); // must be 0 for compressed textures
+            this.glInternalFormat = headerDataView.getUint32(4 * dataSize, littleEndian); // the value of arg passed to gl.compressedTexImage2D(,,x,,,,)
+            this.glBaseInternalFormat = headerDataView.getUint32(5 * dataSize, littleEndian); // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only)
+            this.pixelWidth = headerDataView.getUint32(6 * dataSize, littleEndian); // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,)
+            this.pixelHeight = headerDataView.getUint32(7 * dataSize, littleEndian); // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,)
+            this.pixelDepth = headerDataView.getUint32(8 * dataSize, littleEndian); // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,)
+            this.numberOfArrayElements = headerDataView.getUint32(9 * dataSize, littleEndian); // used for texture arrays
+            this.numberOfFaces = headerDataView.getUint32(10 * dataSize, littleEndian); // used for cubemap textures, should either be 1 or 6
+            this.numberOfMipmapLevels = headerDataView.getUint32(11 * dataSize, littleEndian); // number of levels; disregard possibility of 0 for compressed textures
+            this.bytesOfKeyValueData = headerDataView.getUint32(12 * dataSize, littleEndian); // the amount of space after the header for meta-data
             // Make sure we have a compressed type.  Not only reduces work, but probably better to let dev know they are not compressing.
             if (this.glType !== 0) {
                 BABYLON.Tools.Error("only compressed formats currently supported");
@@ -102279,19 +102397,6 @@ var BABYLON;
             // would need to make this more elaborate & adjust checks above to support more than one load type
             this.loadType = KhronosTextureContainer.COMPRESSED_2D;
         }
-        //
-        /**
-         * Revert the endianness of a value.
-         * Not as fast hardware based, but will probably never need to use
-         * @param val defines the value to convert
-         * @returns the new value
-         */
-        KhronosTextureContainer.prototype.switchEndianness = function (val) {
-            return ((val & 0xFF) << 24)
-                | ((val & 0xFF00) << 8)
-                | ((val >> 8) & 0xFF00)
-                | ((val >> 24) & 0xFF);
-        };
         /**
          * Uploads KTX content to a Babylon Texture.
          * It is assumed that the texture has already been created & is currently bound
@@ -117203,7 +117308,7 @@ var BABYLON;
             if (useBilinearMode === void 0) { useBilinearMode = true; }
             var scene = texture.getScene();
             var engine = scene.getEngine();
-            var rtt = new BABYLON.RenderTargetTexture('resized' + texture.name, { width: width, height: height }, scene, !texture.noMipmap, true, texture._texture.type, false, texture._samplingMode, false);
+            var rtt = new BABYLON.RenderTargetTexture('resized' + texture.name, { width: width, height: height }, scene, !texture.noMipmap, true, texture._texture.type, false, texture.samplingMode, false);
             rtt.wrapU = texture.wrapU;
             rtt.wrapV = texture.wrapV;
             rtt.uOffset = texture.uOffset;

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/babylon.worker.js


+ 226 - 121
dist/preview release/es6.js

@@ -12941,7 +12941,7 @@ var BABYLON;
              * Returns the current version of the framework
              */
             get: function () {
-                return "4.0.0-alpha.11";
+                return "4.0.0-alpha.14";
             },
             enumerable: true,
             configurable: true
@@ -15790,8 +15790,7 @@ var BABYLON;
                         customFallback = true;
                         excludeLoaders.push(loader);
                         BABYLON.Tools.Warn(loader.constructor.name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
-                        _this.createTexture(urlArg, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture, undefined, undefined, excludeLoaders);
-                        return;
+                        _this.createTexture(urlArg, noMipmap, texture.invertY, scene, samplingMode, null, null, buffer, texture, undefined, undefined, excludeLoaders);
                     }
                 }
                 if (!customFallback) {
@@ -15799,8 +15798,7 @@ var BABYLON;
                         texture.onLoadedObservable.remove(onLoadObserver);
                     }
                     if (BABYLON.Tools.UseFallbackTexture) {
-                        _this.createTexture(BABYLON.Tools.fallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture);
-                        return;
+                        _this.createTexture(BABYLON.Tools.fallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, null, buffer, texture);
                     }
                 }
                 if (onError) {
@@ -19539,8 +19537,25 @@ var BABYLON;
          * @returns true if there is an intersection
          */
         BoundingSphere.prototype.isInFrustum = function (frustumPlanes) {
+            var center = this.centerWorld;
+            var radius = this.radiusWorld;
+            for (var i = 0; i < 6; i++) {
+                if (frustumPlanes[i].dotCoordinate(center) <= -radius) {
+                    return false;
+                }
+            }
+            return true;
+        };
+        /**
+         * Tests if the bounding sphere center is in between the frustum planes.
+         * Used for optimistic fast inclusion.
+         * @param frustumPlanes defines the frustum planes to test
+         * @returns true if the sphere center is in between the frustum planes
+         */
+        BoundingSphere.prototype.isCenterInFrustum = function (frustumPlanes) {
+            var center = this.centerWorld;
             for (var i = 0; i < 6; i++) {
-                if (frustumPlanes[i].dotCoordinate(this.centerWorld) <= -this.radiusWorld) {
+                if (frustumPlanes[i].dotCoordinate(center) < 0) {
                     return false;
                 }
             }
@@ -19977,15 +19992,22 @@ var BABYLON;
         /**
          * Returns `true` if the bounding info is within the frustum defined by the passed array of planes.
          * @param frustumPlanes defines the frustum to test
-         * @param strategy defines the strategy to use for the culling (default is BABYLON.Scene.CULLINGSTRATEGY_STANDARD)
+         * @param strategy defines the strategy to use for the culling (default is BABYLON.AbstractMesh.CULLINGSTRATEGY_STANDARD)
          * @returns true if the bounding info is in the frustum planes
          */
         BoundingInfo.prototype.isInFrustum = function (frustumPlanes, strategy) {
             if (strategy === void 0) { strategy = BABYLON.AbstractMesh.CULLINGSTRATEGY_STANDARD; }
+            var inclusionTest = (strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION || strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY);
+            if (inclusionTest) {
+                if (this.boundingSphere.isCenterInFrustum(frustumPlanes)) {
+                    return true;
+                }
+            }
             if (!this.boundingSphere.isInFrustum(frustumPlanes)) {
                 return false;
             }
-            if (strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY) {
+            var bSphereOnlyTest = (strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY || strategy === BABYLON.AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY);
+            if (bSphereOnlyTest) {
                 return true;
             }
             return this.boundingBox.isInFrustum(frustumPlanes);
@@ -21240,7 +21262,16 @@ var BABYLON;
             if (scene === void 0) { scene = null; }
             var _this = _super.call(this, name, scene, false) || this;
             _this._facetData = new _FacetDataStorage();
-            /** Gets ot sets the culling strategy to use to find visible meshes */
+            /**
+             * The culling strategy to use to check whether the mesh must be rendered or not.
+             * This value can be changed at any time and will be used on the next render mesh selection.
+             * The possible values are :
+             * - AbstractMesh.CULLINGSTRATEGY_STANDARD
+             * - AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY
+             * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION
+             * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY
+             * Please read each static variable documentation to get details about the culling process.
+             * */
             _this.cullingStrategy = AbstractMesh.CULLINGSTRATEGY_STANDARD;
             // Events
             /**
@@ -23041,10 +23072,40 @@ var BABYLON;
         AbstractMesh.OCCLUSION_ALGORITHM_TYPE_ACCURATE = 0;
         /** Use a conservative occlusion algorithm */
         AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE = 1;
-        /** Default culling strategy with bounding box and bounding sphere and then frustum culling */
+        /** Default culling strategy : this is an exclusion test and it's the more accurate.
+         *  Test order :
+         *  Is the bounding sphere outside the frustum ?
+         *  If not, are the bounding box vertices outside the frustum ?
+         *  It not, then the cullable object is in the frustum.
+         */
         AbstractMesh.CULLINGSTRATEGY_STANDARD = 0;
-        /** Culling strategy with bounding sphere only and then frustum culling */
+        /** Culling strategy : Bounding Sphere Only.
+         *  This is an exclusion test. It's faster than the standard strategy because the bounding box is not tested.
+         *  It's also less accurate than the standard because some not visible objects can still be selected.
+         *  Test : is the bounding sphere outside the frustum ?
+         *  If not, then the cullable object is in the frustum.
+         */
         AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY = 1;
+        /** Culling strategy : Optimistic Inclusion.
+         *  This in an inclusion test first, then the standard exclusion test.
+         *  This can be faster when a cullable object is expected to be almost always in the camera frustum.
+         *  This could also be a little slower than the standard test when the tested object center is not the frustum but one of its bounding box vertex is still inside.
+         *  Anyway, it's as accurate as the standard strategy.
+         *  Test :
+         *  Is the cullable object bounding sphere center in the frustum ?
+         *  If not, apply the default culling strategy.
+         */
+        AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION = 2;
+        /** Culling strategy : Optimistic Inclusion then Bounding Sphere Only.
+         *  This in an inclusion test first, then the bounding sphere only exclusion test.
+         *  This can be the fastest test when a cullable object is expected to be almost always in the camera frustum.
+         *  This could also be a little slower than the BoundingSphereOnly strategy when the tested object center is not in the frustum but its bounding sphere still intersects it.
+         *  It's less accurate than the standard strategy and as accurate as the BoundingSphereOnly strategy.
+         *  Test :
+         *  Is the cullable object bounding sphere center in the frustum ?
+         *  If not, apply the Bounding Sphere Only strategy. No Bounding Box is tested here.
+         */
+        AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY = 3;
         return AbstractMesh;
     }(BABYLON.TransformNode));
     BABYLON.AbstractMesh = AbstractMesh;
@@ -26339,7 +26400,7 @@ var BABYLON;
             /**
              * an optional map from Geometry Id to Geometry index in the 'geometries' array
              */
-            _this.geometriesById = null;
+            _this.geometriesByUniqueId = null;
             _this._defaultMeshCandidates = {
                 data: [],
                 length: 0
@@ -26379,10 +26440,10 @@ var BABYLON;
                 _this._imageProcessingConfiguration = new BABYLON.ImageProcessingConfiguration();
             }
             _this.setDefaultCandidateProviders();
-            if (options && options.useGeometryIdsMap === true) {
-                _this.geometriesById = {};
+            if (options && options.useGeometryUniqueIdsMap === true) {
+                _this.geometriesByUniqueId = {};
             }
-            _this.useMaterialMeshMap = options && options.useGeometryIdsMap || false;
+            _this.useMaterialMeshMap = options && options.useGeometryUniqueIdsMap || false;
             _this.useClonedMeshhMap = options && options.useClonedMeshhMap || false;
             _this._engine.onNewSceneAddedObservable.notifyObservers(_this);
             return _this;
@@ -28624,8 +28685,8 @@ var BABYLON;
          * @param newGeometry The geometry to add
          */
         Scene.prototype.addGeometry = function (newGeometry) {
-            if (this.geometriesById) {
-                this.geometriesById[newGeometry.id] = this.geometries.length;
+            if (this.geometriesByUniqueId) {
+                this.geometriesByUniqueId[newGeometry.uniqueId] = this.geometries.length;
             }
             this.geometries.push(newGeometry);
         };
@@ -28857,29 +28918,29 @@ var BABYLON;
          * @return the geometry or null if none found.
          */
         Scene.prototype.getGeometryByID = function (id) {
-            if (this.geometriesById) {
-                var index_1 = this.geometriesById[id];
+            for (var index = 0; index < this.geometries.length; index++) {
+                if (this.geometries[index].id === id) {
+                    return this.geometries[index];
+                }
+            }
+            return null;
+        };
+        Scene.prototype._getGeometryByUniqueID = function (uniqueId) {
+            if (this.geometriesByUniqueId) {
+                var index_1 = this.geometriesByUniqueId[uniqueId];
                 if (index_1 !== undefined) {
                     return this.geometries[index_1];
                 }
             }
             else {
                 for (var index = 0; index < this.geometries.length; index++) {
-                    if (this.geometries[index].id === id) {
+                    if (this.geometries[index].uniqueId === uniqueId) {
                         return this.geometries[index];
                     }
                 }
             }
             return null;
         };
-        Scene.prototype._getGeometryByUniqueID = function (id) {
-            for (var index = 0; index < this.geometries.length; index++) {
-                if (this.geometries[index].uniqueId === id) {
-                    return this.geometries[index];
-                }
-            }
-            return null;
-        };
         /**
          * Add a new geometry to this scene
          * @param geometry defines the geometry to be added to the scene.
@@ -28905,8 +28966,8 @@ var BABYLON;
          */
         Scene.prototype.removeGeometry = function (geometry) {
             var index;
-            if (this.geometriesById) {
-                index = this.geometriesById[geometry.id];
+            if (this.geometriesByUniqueId) {
+                index = this.geometriesByUniqueId[geometry.uniqueId];
                 if (index === undefined) {
                     return false;
                 }
@@ -28920,9 +28981,9 @@ var BABYLON;
             if (index !== this.geometries.length - 1) {
                 var lastGeometry = this.geometries[this.geometries.length - 1];
                 this.geometries[index] = lastGeometry;
-                if (this.geometriesById) {
-                    this.geometriesById[lastGeometry.id] = index;
-                    this.geometriesById[geometry.id] = undefined;
+                if (this.geometriesByUniqueId) {
+                    this.geometriesByUniqueId[lastGeometry.uniqueId] = index;
+                    this.geometriesByUniqueId[geometry.uniqueId] = undefined;
                 }
             }
             this.geometries.pop();
@@ -31735,14 +31796,6 @@ var BABYLON;
              */
             this.anisotropicFilteringLevel = BaseTexture.DEFAULT_ANISOTROPIC_FILTERING_LEVEL;
             /**
-             * Define if the texture is a cube texture or if false a 2d texture.
-             */
-            this.isCube = false;
-            /**
-             * Define if the texture is a 3d texture (webgl 2) or if false a 2d texture.
-             */
-            this.is3D = false;
-            /**
              * Define if the texture contains data in gamma space (most of the png/jpg aside bump).
              * HDR texture are usually stored in linear space.
              * This only impacts the PBR and Background materials
@@ -31831,6 +31884,44 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(BaseTexture.prototype, "isCube", {
+            /**
+             * Define if the texture is a cube texture or if false a 2d texture.
+             */
+            get: function () {
+                if (!this._texture) {
+                    return false;
+                }
+                return this._texture.isCube;
+            },
+            set: function (value) {
+                if (!this._texture) {
+                    return;
+                }
+                this._texture.isCube = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(BaseTexture.prototype, "is3D", {
+            /**
+             * Define if the texture is a 3d texture (webgl 2) or if false a 2d texture.
+             */
+            get: function () {
+                if (!this._texture) {
+                    return false;
+                }
+                return this._texture.is3D;
+            },
+            set: function (value) {
+                if (!this._texture) {
+                    return;
+                }
+                this._texture.is3D = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(BaseTexture.prototype, "isRGBD", {
             /**
              * Gets whether or not the texture contains RGBD data.
@@ -32053,7 +32144,6 @@ var BABYLON;
             if (!scene) {
                 return;
             }
-            this._samplingMode = samplingMode;
             scene.getEngine().updateTextureSamplingMode(samplingMode, this._texture);
         };
         /**
@@ -32346,10 +32436,10 @@ var BABYLON;
         ], BaseTexture.prototype, "anisotropicFilteringLevel", void 0);
         __decorate([
             BABYLON.serialize()
-        ], BaseTexture.prototype, "isCube", void 0);
+        ], BaseTexture.prototype, "isCube", null);
         __decorate([
             BABYLON.serialize()
-        ], BaseTexture.prototype, "is3D", void 0);
+        ], BaseTexture.prototype, "is3D", null);
         __decorate([
             BABYLON.serialize()
         ], BaseTexture.prototype, "gammaSpace", void 0);
@@ -32460,6 +32550,8 @@ var BABYLON;
              * Defines the center of rotation (W)
              */
             _this.wRotationCenter = 0.5;
+            /** @hidden */
+            _this._initialSamplingMode = Texture.BILINEAR_SAMPLINGMODE;
             /**
              * Observable triggered once the texture has been loaded.
              */
@@ -32469,7 +32561,7 @@ var BABYLON;
             _this.url = url;
             _this._noMipmap = noMipmap;
             _this._invertY = invertY;
-            _this._samplingMode = samplingMode;
+            _this._initialSamplingMode = samplingMode;
             _this._buffer = buffer;
             _this._deleteBuffer = deleteBuffer;
             if (format) {
@@ -32502,7 +32594,7 @@ var BABYLON;
             _this._texture = _this._getFromCache(_this.url, noMipmap, samplingMode);
             if (!_this._texture) {
                 if (!scene.useDelayedTextureLoading) {
-                    _this._texture = scene.getEngine().createTexture(_this.url, noMipmap, invertY, scene, _this._samplingMode, load, onError, _this._buffer, undefined, _this._format);
+                    _this._texture = scene.getEngine().createTexture(_this.url, noMipmap, invertY, scene, samplingMode, load, onError, _this._buffer, undefined, _this._format);
                     if (deleteBuffer) {
                         delete _this._buffer;
                     }
@@ -32552,7 +32644,10 @@ var BABYLON;
              * Get the current sampling mode associated with the texture.
              */
             get: function () {
-                return this._samplingMode;
+                if (!this._texture) {
+                    return this._initialSamplingMode;
+                }
+                return this._texture.samplingMode;
             },
             enumerable: true,
             configurable: true
@@ -32600,9 +32695,9 @@ var BABYLON;
                 return;
             }
             this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
-            this._texture = this._getFromCache(this.url, this._noMipmap, this._samplingMode);
+            this._texture = this._getFromCache(this.url, this._noMipmap, this.samplingMode);
             if (!this._texture) {
-                this._texture = scene.getEngine().createTexture(this.url, this._noMipmap, this._invertY, scene, this._samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer, null, this._format);
+                this._texture = scene.getEngine().createTexture(this.url, this._noMipmap, this._invertY, scene, this.samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer, null, this._format);
                 if (this._deleteBuffer) {
                     delete this._buffer;
                 }
@@ -32741,7 +32836,7 @@ var BABYLON;
         Texture.prototype.clone = function () {
             var _this = this;
             return BABYLON.SerializationHelper.Clone(function () {
-                return new Texture(_this._texture ? _this._texture.url : null, _this.getScene(), _this._noMipmap, _this._invertY, _this._samplingMode);
+                return new Texture(_this._texture ? _this._texture.url : null, _this.getScene(), _this._noMipmap, _this._invertY, _this.samplingMode);
             }, this);
         };
         /**
@@ -32847,7 +32942,7 @@ var BABYLON;
             // Update Sampling Mode
             if (parsedTexture.samplingMode) {
                 var sampling = parsedTexture.samplingMode;
-                if (texture && texture._samplingMode !== sampling) {
+                if (texture && texture.samplingMode !== sampling) {
                     texture.updateSamplingMode(sampling);
                 }
             }
@@ -33104,7 +33199,9 @@ var BABYLON;
                 // Deep copy
                 BABYLON.Tools.DeepCopy(source, _this, ["name", "material", "skeleton", "instances", "parent", "uniqueId",
                     "source", "metadata", "hasLODLevels", "geometry", "isBlocked", "areNormalsFrozen",
-                    "onBeforeDrawObservable", "onBeforeRenderObservable", "onAfterRenderObservable", "onBeforeDraw"
+                    "onBeforeDrawObservable", "onBeforeRenderObservable", "onAfterRenderObservable", "onBeforeDraw",
+                    "onAfterWorldMatrixUpdateObservable", "onCollideObservable", "onCollisionPositionChangeObservable", "onRebuildObservable",
+                    "onDisposeObservable"
                 ], ["_poseMatrix"]);
                 // Source mesh
                 _this._source = source;
@@ -41557,7 +41654,15 @@ var BABYLON;
                 this.setIndices(indices, null, true);
             }
             else {
+                var needToUpdateSubMeshes = indices.length !== this._indices.length;
+                this._indices = indices;
                 this._engine.updateDynamicIndexBuffer(this._indexBuffer, indices, offset);
+                if (needToUpdateSubMeshes) {
+                    for (var _i = 0, _a = this._meshes; _i < _a.length; _i++) {
+                        var mesh = _a[_i];
+                        mesh._createGlobalSubMesh(true);
+                    }
+                }
             }
         };
         /**
@@ -41581,10 +41686,9 @@ var BABYLON;
             if (totalVertices != undefined) { // including null and undefined
                 this._totalVertices = totalVertices;
             }
-            var meshes = this._meshes;
-            var numOfMeshes = meshes.length;
-            for (var index = 0; index < numOfMeshes; index++) {
-                meshes[index]._createGlobalSubMesh(true);
+            for (var _i = 0, _a = this._meshes; _i < _a.length; _i++) {
+                var mesh = _a[_i];
+                mesh._createGlobalSubMesh(true);
             }
             this.notifyUpdate();
         };
@@ -41890,17 +41994,19 @@ var BABYLON;
             for (kind in this._vertexBuffers) {
                 // using slice() to make a copy of the array and not just reference it
                 var data = this.getVerticesData(kind);
-                if (data instanceof Float32Array) {
-                    vertexData.set(new Float32Array(data), kind);
-                }
-                else {
-                    vertexData.set(data.slice(0), kind);
-                }
-                if (!stopChecking) {
-                    var vb = this.getVertexBuffer(kind);
-                    if (vb) {
-                        updatable = vb.isUpdatable();
-                        stopChecking = !updatable;
+                if (data) {
+                    if (data instanceof Float32Array) {
+                        vertexData.set(new Float32Array(data), kind);
+                    }
+                    else {
+                        vertexData.set(data.slice(0), kind);
+                    }
+                    if (!stopChecking) {
+                        var vb = this.getVertexBuffer(kind);
+                        if (vb) {
+                            updatable = vb.isUpdatable();
+                            stopChecking = !updatable;
+                        }
                     }
                 }
             }
@@ -45239,10 +45345,10 @@ var BABYLON;
         };
         /**
          * Creates a standard material from parsed material data
-         * @param source defines the JSON represnetation of the material
+         * @param source defines the JSON representation of the material
          * @param scene defines the hosting scene
          * @param rootUrl defines the root URL to use to load textures and relative dependencies
-         * @returns a new material
+         * @returns a new standard material
          */
         StandardMaterial.Parse = function (source, scene, rootUrl) {
             return BABYLON.SerializationHelper.Parse(function () { return new StandardMaterial(source.name, scene); }, source, scene, rootUrl);
@@ -67051,7 +67157,7 @@ var BABYLON;
          */
         function DebugLayer(scene) {
             var _this = this;
-            this.BJSINSPECTOR = typeof INSPECTOR !== 'undefined' ? INSPECTOR : undefined;
+            this.BJSINSPECTOR = this._getGlobalInspector();
             /**
              * Observable triggered when a property is changed through the inspector.
              */
@@ -67070,9 +67176,21 @@ var BABYLON;
                 return;
             }
             var userOptions = __assign({ overlay: false, showExplorer: true, showInspector: true, embedMode: false, handleResize: true, enablePopup: true }, config);
-            this.BJSINSPECTOR = this.BJSINSPECTOR || typeof INSPECTOR !== 'undefined' ? INSPECTOR : undefined;
+            this.BJSINSPECTOR = this.BJSINSPECTOR || this._getGlobalInspector();
             this.BJSINSPECTOR.Inspector.Show(this._scene, userOptions);
         };
+        /** Get the inspector from bundle or global */
+        DebugLayer.prototype._getGlobalInspector = function () {
+            // UMD Global name detection from Webpack Bundle UMD Name.
+            if (typeof INSPECTOR !== 'undefined') {
+                return INSPECTOR;
+            }
+            // In case of module let s check the global emitted from the Inspector entry point.
+            if (BABYLON && BABYLON.Inspector) {
+                return BABYLON;
+            }
+            return undefined;
+        };
         /**
          * Get if the inspector is visible or not.
          * @returns true if visible otherwise, false
@@ -70140,7 +70258,7 @@ var BABYLON;
     var MeshBuilder = /** @class */ (function () {
         function MeshBuilder() {
         }
-        MeshBuilder.updateSideOrientation = function (orientation) {
+        MeshBuilder._UpdateSideOrientation = function (orientation) {
             if (orientation == BABYLON.Mesh.DOUBLESIDE) {
                 return BABYLON.Mesh.DOUBLESIDE;
             }
@@ -70167,7 +70285,7 @@ var BABYLON;
         MeshBuilder.CreateBox = function (name, options, scene) {
             if (scene === void 0) { scene = null; }
             var box = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             box._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateBox(options);
             vertexData.applyToMesh(box, options.updatable);
@@ -70191,7 +70309,7 @@ var BABYLON;
          */
         MeshBuilder.CreateSphere = function (name, options, scene) {
             var sphere = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             sphere._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateSphere(options);
             vertexData.applyToMesh(sphere, options.updatable);
@@ -70214,7 +70332,7 @@ var BABYLON;
         MeshBuilder.CreateDisc = function (name, options, scene) {
             if (scene === void 0) { scene = null; }
             var disc = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             disc._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateDisc(options);
             vertexData.applyToMesh(disc, options.updatable);
@@ -70237,7 +70355,7 @@ var BABYLON;
          */
         MeshBuilder.CreateIcoSphere = function (name, options, scene) {
             var sphere = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             sphere._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateIcoSphere(options);
             vertexData.applyToMesh(sphere, options.updatable);
@@ -70271,7 +70389,7 @@ var BABYLON;
             var pathArray = options.pathArray;
             var closeArray = options.closeArray;
             var closePath = options.closePath;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var instance = options.instance;
             var updatable = options.updatable;
             if (instance) { // existing ribbon instance update
@@ -70409,7 +70527,7 @@ var BABYLON;
          */
         MeshBuilder.CreateCylinder = function (name, options, scene) {
             var cylinder = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             cylinder._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateCylinder(options);
             vertexData.applyToMesh(cylinder, options.updatable);
@@ -70431,7 +70549,7 @@ var BABYLON;
          */
         MeshBuilder.CreateTorus = function (name, options, scene) {
             var torus = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             torus._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateTorus(options);
             vertexData.applyToMesh(torus, options.updatable);
@@ -70454,7 +70572,7 @@ var BABYLON;
          */
         MeshBuilder.CreateTorusKnot = function (name, options, scene) {
             var torusKnot = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             torusKnot._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreateTorusKnot(options);
             vertexData.applyToMesh(torusKnot, options.updatable);
@@ -70649,7 +70767,7 @@ var BABYLON;
             var rotation = options.rotation || 0;
             var cap = (options.cap === 0) ? 0 : options.cap || BABYLON.Mesh.NO_CAP;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var instance = options.instance || null;
             var invertUV = options.invertUV || false;
             return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, scale, rotation, null, null, false, false, cap, false, scene, updatable ? true : false, sideOrientation, instance, invertUV, options.frontUVs || null, options.backUVs || null);
@@ -70689,7 +70807,7 @@ var BABYLON;
             var ribbonClosePath = options.ribbonClosePath || false;
             var cap = (options.cap === 0) ? 0 : options.cap || BABYLON.Mesh.NO_CAP;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var instance = options.instance;
             var invertUV = options.invertUV || false;
             return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, cap, true, scene, updatable ? true : false, sideOrientation, instance || null, invertUV, options.frontUVs || null, options.backUVs || null);
@@ -70722,7 +70840,7 @@ var BABYLON;
             var tessellation = options.tessellation || 64;
             var clip = options.clip || 0;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var cap = options.cap || BABYLON.Mesh.NO_CAP;
             var pi2 = Math.PI * 2;
             var paths = new Array();
@@ -70768,7 +70886,7 @@ var BABYLON;
          */
         MeshBuilder.CreatePlane = function (name, options, scene) {
             var plane = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             plane._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreatePlane(options);
             vertexData.applyToMesh(plane, options.updatable);
@@ -70912,7 +71030,7 @@ var BABYLON;
          * @returns the polygon mesh
          */
         MeshBuilder.CreatePolygon = function (name, options, scene) {
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var shape = options.shape;
             var holes = options.holes || [];
             var depth = options.depth || 0;
@@ -70988,7 +71106,7 @@ var BABYLON;
             var cap = options.cap || BABYLON.Mesh.NO_CAP;
             var invertUV = options.invertUV || false;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             options.arc = options.arc && (options.arc <= 0.0 || options.arc > 1.0) ? 1.0 : options.arc || 1.0;
             // tube geometry
             var tubePathArray = function (path, path3D, circlePaths, radius, tessellation, radiusFunction, cap, arc) {
@@ -71099,7 +71217,7 @@ var BABYLON;
          */
         MeshBuilder.CreatePolyhedron = function (name, options, scene) {
             var polyhedron = new BABYLON.Mesh(name, scene);
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             polyhedron._originalBuilderSideOrientation = options.sideOrientation;
             var vertexData = BABYLON.VertexData.CreatePolyhedron(options);
             vertexData.applyToMesh(polyhedron, options.updatable);
@@ -75618,7 +75736,7 @@ var BABYLON;
             this._canvas.width = textureSize.width;
             this._canvas.height = textureSize.height;
             this.releaseInternalTexture();
-            this._texture = this._engine.createDynamicTexture(textureSize.width, textureSize.height, this._generateMipMaps, this._samplingMode);
+            this._texture = this._engine.createDynamicTexture(textureSize.width, textureSize.height, this._generateMipMaps, this.samplingMode);
         };
         /**
          * Scales the texture
@@ -75798,7 +75916,7 @@ var BABYLON;
                     _this.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
                     _this._generateMipMaps = false;
                 }
-                _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this._samplingMode);
+                _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this.samplingMode);
                 if (!_this.video.autoplay && !_this._settings.poster) {
                     var oldHandler_1 = _this.video.onplaying;
                     var error_1 = false;
@@ -75866,7 +75984,7 @@ var BABYLON;
             };
             _this._engine = _this.getScene().getEngine();
             _this._generateMipMaps = generateMipMaps;
-            _this._samplingMode = samplingMode;
+            _this._initialSamplingMode = samplingMode;
             _this.autoUpdateTexture = settings.autoUpdateTexture;
             _this.name = name || _this._getName(src);
             _this.video = _this._getVideo(src);
@@ -102237,23 +102355,23 @@ var BABYLON;
                 BABYLON.Tools.Error("texture missing KTX identifier");
                 return;
             }
-            // load the reset of the header in native 32 bit int
-            var header = new Int32Array(this.arrayBuffer, 12, 13);
-            // determine of the remaining header values are recorded in the opposite endianness & require conversion
-            var oppositeEndianess = header[0] === 0x01020304;
-            // read all the header elements in order they exist in the file, without modification (sans endainness)
-            this.glType = oppositeEndianess ? this.switchEndianness(header[1]) : header[1]; // must be 0 for compressed textures
-            this.glTypeSize = oppositeEndianess ? this.switchEndianness(header[2]) : header[2]; // must be 1 for compressed textures
-            this.glFormat = oppositeEndianess ? this.switchEndianness(header[3]) : header[3]; // must be 0 for compressed textures
-            this.glInternalFormat = oppositeEndianess ? this.switchEndianness(header[4]) : header[4]; // the value of arg passed to gl.compressedTexImage2D(,,x,,,,)
-            this.glBaseInternalFormat = oppositeEndianess ? this.switchEndianness(header[5]) : header[5]; // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only)
-            this.pixelWidth = oppositeEndianess ? this.switchEndianness(header[6]) : header[6]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,)
-            this.pixelHeight = oppositeEndianess ? this.switchEndianness(header[7]) : header[7]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,)
-            this.pixelDepth = oppositeEndianess ? this.switchEndianness(header[8]) : header[8]; // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,)
-            this.numberOfArrayElements = oppositeEndianess ? this.switchEndianness(header[9]) : header[9]; // used for texture arrays
-            this.numberOfFaces = oppositeEndianess ? this.switchEndianness(header[10]) : header[10]; // used for cubemap textures, should either be 1 or 6
-            this.numberOfMipmapLevels = oppositeEndianess ? this.switchEndianness(header[11]) : header[11]; // number of levels; disregard possibility of 0 for compressed textures
-            this.bytesOfKeyValueData = oppositeEndianess ? this.switchEndianness(header[12]) : header[12]; // the amount of space after the header for meta-data
+            // load the reset of the header in native 32 bit uint
+            var dataSize = Uint32Array.BYTES_PER_ELEMENT;
+            var headerDataView = new DataView(this.arrayBuffer, 12, 13 * dataSize);
+            var endianness = headerDataView.getUint32(0, true);
+            var littleEndian = endianness === 0x04030201;
+            this.glType = headerDataView.getUint32(1 * dataSize, littleEndian); // must be 0 for compressed textures
+            this.glTypeSize = headerDataView.getUint32(2 * dataSize, littleEndian); // must be 1 for compressed textures
+            this.glFormat = headerDataView.getUint32(3 * dataSize, littleEndian); // must be 0 for compressed textures
+            this.glInternalFormat = headerDataView.getUint32(4 * dataSize, littleEndian); // the value of arg passed to gl.compressedTexImage2D(,,x,,,,)
+            this.glBaseInternalFormat = headerDataView.getUint32(5 * dataSize, littleEndian); // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only)
+            this.pixelWidth = headerDataView.getUint32(6 * dataSize, littleEndian); // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,)
+            this.pixelHeight = headerDataView.getUint32(7 * dataSize, littleEndian); // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,)
+            this.pixelDepth = headerDataView.getUint32(8 * dataSize, littleEndian); // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,)
+            this.numberOfArrayElements = headerDataView.getUint32(9 * dataSize, littleEndian); // used for texture arrays
+            this.numberOfFaces = headerDataView.getUint32(10 * dataSize, littleEndian); // used for cubemap textures, should either be 1 or 6
+            this.numberOfMipmapLevels = headerDataView.getUint32(11 * dataSize, littleEndian); // number of levels; disregard possibility of 0 for compressed textures
+            this.bytesOfKeyValueData = headerDataView.getUint32(12 * dataSize, littleEndian); // the amount of space after the header for meta-data
             // Make sure we have a compressed type.  Not only reduces work, but probably better to let dev know they are not compressing.
             if (this.glType !== 0) {
                 BABYLON.Tools.Error("only compressed formats currently supported");
@@ -102279,19 +102397,6 @@ var BABYLON;
             // would need to make this more elaborate & adjust checks above to support more than one load type
             this.loadType = KhronosTextureContainer.COMPRESSED_2D;
         }
-        //
-        /**
-         * Revert the endianness of a value.
-         * Not as fast hardware based, but will probably never need to use
-         * @param val defines the value to convert
-         * @returns the new value
-         */
-        KhronosTextureContainer.prototype.switchEndianness = function (val) {
-            return ((val & 0xFF) << 24)
-                | ((val & 0xFF00) << 8)
-                | ((val >> 8) & 0xFF00)
-                | ((val >> 24) & 0xFF);
-        };
         /**
          * Uploads KTX content to a Babylon Texture.
          * It is assumed that the texture has already been created & is currently bound
@@ -117203,7 +117308,7 @@ var BABYLON;
             if (useBilinearMode === void 0) { useBilinearMode = true; }
             var scene = texture.getScene();
             var engine = scene.getEngine();
-            var rtt = new BABYLON.RenderTargetTexture('resized' + texture.name, { width: width, height: height }, scene, !texture.noMipmap, true, texture._texture.type, false, texture._samplingMode, false);
+            var rtt = new BABYLON.RenderTargetTexture('resized' + texture.name, { width: width, height: height }, scene, !texture.noMipmap, true, texture._texture.type, false, texture.samplingMode, false);
             rtt.wrapU = texture.wrapU;
             rtt.wrapV = texture.wrapV;
             rtt.uOffset = texture.uOffset;

+ 1 - 1
dist/preview release/glTF2Interface/package.json

@@ -1,7 +1,7 @@
 {
     "name": "babylonjs-gltf2interface",
     "description": "A typescript declaration of babylon's gltf2 inteface.",
-    "version": "4.0.0-alpha.11",
+    "version": "4.0.0-alpha.14",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 88 - 0
dist/preview release/gui/babylon.gui.d.ts

@@ -70,6 +70,22 @@ declare module BABYLON.GUI {
                 */
             onControlPickedObservable: BABYLON.Observable<Control>;
             /**
+                * BABYLON.Observable event triggered before layout is evaluated
+                */
+            onBeginLayoutObservable: BABYLON.Observable<AdvancedDynamicTexture>;
+            /**
+                * BABYLON.Observable event triggered after the layout was evaluated
+                */
+            onEndLayoutObservable: BABYLON.Observable<AdvancedDynamicTexture>;
+            /**
+                * BABYLON.Observable event triggered before the texture is rendered
+                */
+            onBeginRenderObservable: BABYLON.Observable<AdvancedDynamicTexture>;
+            /**
+                * BABYLON.Observable event triggered after the texture was rendered
+                */
+            onEndRenderObservable: BABYLON.Observable<AdvancedDynamicTexture>;
+            /**
                 * Gets or sets a boolean defining if alpha is stored as premultiplied
                 */
             premulAlpha: boolean;
@@ -249,6 +265,47 @@ declare module BABYLON.GUI {
 }
 declare module BABYLON.GUI {
     /**
+        * This class can be used to get instrumentation data from a AdvancedDynamicTexture object
+        */
+    export class AdvancedDynamicTextureInstrumentation implements BABYLON.IDisposable {
+            /**
+                * Define the instrumented AdvancedDynamicTexture.
+                */
+            texture: AdvancedDynamicTexture;
+            /**
+                * Gets the perf counter used to capture render time
+                */
+            readonly renderTimeCounter: BABYLON.PerfCounter;
+            /**
+                * Gets the perf counter used to capture layout time
+                */
+            readonly layoutTimeCounter: BABYLON.PerfCounter;
+            /**
+                * Enable or disable the render time capture
+                */
+            captureRenderTime: boolean;
+            /**
+                * Enable or disable the layout time capture
+                */
+            captureLayoutTime: boolean;
+            /**
+                * Instantiates a new advanced dynamic texture instrumentation.
+                * This class can be used to get instrumentation data from an AdvancedDynamicTexture object
+                * @param texture Defines the AdvancedDynamicTexture to instrument
+                */
+            constructor(
+            /**
+                * Define the instrumented AdvancedDynamicTexture.
+                */
+            texture: AdvancedDynamicTexture);
+            /**
+                * Dispose and release associated resources.
+                */
+            dispose(): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
         * Class used to transport BABYLON.Vector2 information for pointer events
         */
     export class Vector2WithInfo extends BABYLON.Vector2 {
@@ -2055,6 +2112,14 @@ declare module BABYLON.GUI {
      */
     export class ScrollViewer extends Rectangle {
             /**
+                * Gets the horizontal scrollbar
+                */
+            readonly horizontalBar: ScrollBar;
+            /**
+                * Gets the vertical scrollbar
+                */
+            readonly verticalBar: ScrollBar;
+            /**
                 * Adds a new control to the current container
                 * @param control defines the control to add
                 * @returns the current container
@@ -2973,4 +3038,27 @@ declare module BABYLON.GUI {
             getClassName(): string;
             static Parse(source: any, scene: BABYLON.Scene, rootUrl: string): FluentMaterial;
     }
+}
+declare module BABYLON.GUI {
+    /**
+        * Class used to create slider controls
+        */
+    export class ScrollBar extends BaseSlider {
+            name?: string | undefined;
+            /** Gets or sets border color */
+            borderColor: string;
+            /** Gets or sets background color */
+            background: string;
+            /**
+                * Creates a new Slider
+                * @param name defines the control name
+                */
+            constructor(name?: string | undefined);
+            protected _getTypeName(): string;
+            protected _getThumbThickness(): number;
+            _draw(context: CanvasRenderingContext2D): void;
+            /** @hidden */
+            protected _updateValueFromPointer(x: number, y: number): void;
+            _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
+    }
 }

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/gui/babylon.gui.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


+ 185 - 0
dist/preview release/gui/babylon.gui.module.d.ts

@@ -11,6 +11,7 @@ declare module 'babylonjs-gui' {
 declare module 'babylonjs-gui/2D' {
     export * from "babylonjs-gui/2D/controls";
     export * from "babylonjs-gui/2D/advancedDynamicTexture";
+    export * from "babylonjs-gui/2D/adtInstrumentation";
     export * from "babylonjs-gui/2D/math2D";
     export * from "babylonjs-gui/2D/measure";
     export * from "babylonjs-gui/2D/multiLinePoint";
@@ -116,6 +117,22 @@ declare module 'babylonjs-gui/2D/advancedDynamicTexture' {
                 */
             onControlPickedObservable: Observable<Control>;
             /**
+                * Observable event triggered before layout is evaluated
+                */
+            onBeginLayoutObservable: Observable<AdvancedDynamicTexture>;
+            /**
+                * Observable event triggered after the layout was evaluated
+                */
+            onEndLayoutObservable: Observable<AdvancedDynamicTexture>;
+            /**
+                * Observable event triggered before the texture is rendered
+                */
+            onBeginRenderObservable: Observable<AdvancedDynamicTexture>;
+            /**
+                * Observable event triggered after the texture was rendered
+                */
+            onEndRenderObservable: Observable<AdvancedDynamicTexture>;
+            /**
                 * Gets or sets a boolean defining if alpha is stored as premultiplied
                 */
             premulAlpha: boolean;
@@ -294,6 +311,50 @@ declare module 'babylonjs-gui/2D/advancedDynamicTexture' {
     }
 }
 
+declare module 'babylonjs-gui/2D/adtInstrumentation' {
+    import { IDisposable, PerfCounter } from "babylonjs";
+    import { AdvancedDynamicTexture } from "babylonjs-gui/2D/advancedDynamicTexture";
+    /**
+        * This class can be used to get instrumentation data from a AdvancedDynamicTexture object
+        */
+    export class AdvancedDynamicTextureInstrumentation implements IDisposable {
+            /**
+                * Define the instrumented AdvancedDynamicTexture.
+                */
+            texture: AdvancedDynamicTexture;
+            /**
+                * Gets the perf counter used to capture render time
+                */
+            readonly renderTimeCounter: PerfCounter;
+            /**
+                * Gets the perf counter used to capture layout time
+                */
+            readonly layoutTimeCounter: PerfCounter;
+            /**
+                * Enable or disable the render time capture
+                */
+            captureRenderTime: boolean;
+            /**
+                * Enable or disable the layout time capture
+                */
+            captureLayoutTime: boolean;
+            /**
+                * Instantiates a new advanced dynamic texture instrumentation.
+                * This class can be used to get instrumentation data from an AdvancedDynamicTexture object
+                * @param texture Defines the AdvancedDynamicTexture to instrument
+                */
+            constructor(
+            /**
+                * Define the instrumented AdvancedDynamicTexture.
+                */
+            texture: AdvancedDynamicTexture);
+            /**
+                * Dispose and release associated resources.
+                */
+            dispose(): void;
+    }
+}
+
 declare module 'babylonjs-gui/2D/math2D' {
     import { Vector2, Nullable } from "babylonjs";
     /**
@@ -2202,11 +2263,20 @@ declare module 'babylonjs-gui/2D/controls/scrollViewers/scrollViewer' {
     import { Container } from "babylonjs-gui/2D/controls/container";
     import { Nullable } from "babylonjs";
     import { AdvancedDynamicTexture, Measure } from "2D";
+    import { ScrollBar } from "babylonjs-gui/2D/controls/sliders/scrollBar";
     /**
         * Class used to hold a viewer window and sliders in a grid
      */
     export class ScrollViewer extends Rectangle {
             /**
+                * Gets the horizontal scrollbar
+                */
+            readonly horizontalBar: ScrollBar;
+            /**
+                * Gets the vertical scrollbar
+                */
+            readonly verticalBar: ScrollBar;
+            /**
                 * Adds a new control to the current container
                 * @param control defines the control to add
                 * @returns the current container
@@ -3199,6 +3269,33 @@ declare module 'babylonjs-gui/3D/materials/fluentMaterial' {
     }
 }
 
+declare module 'babylonjs-gui/2D/controls/sliders/scrollBar' {
+    import { BaseSlider } from "babylonjs-gui/2D/controls/sliders/baseSlider";
+    import { Control } from "babylonjs-gui/2D/controls";
+    import { Vector2 } from "babylonjs";
+    /**
+        * Class used to create slider controls
+        */
+    export class ScrollBar extends BaseSlider {
+            name?: string | undefined;
+            /** Gets or sets border color */
+            borderColor: string;
+            /** Gets or sets background color */
+            background: string;
+            /**
+                * Creates a new Slider
+                * @param name defines the control name
+                */
+            constructor(name?: string | undefined);
+            protected _getTypeName(): string;
+            protected _getThumbThickness(): number;
+            _draw(context: CanvasRenderingContext2D): void;
+            /** @hidden */
+            protected _updateValueFromPointer(x: number, y: number): void;
+            _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
+    }
+}
+
 
 /*Babylon.js GUI*/
 // Dependencies for this module:
@@ -3272,6 +3369,22 @@ declare module BABYLON.GUI {
                 */
             onControlPickedObservable: BABYLON.Observable<Control>;
             /**
+                * BABYLON.Observable event triggered before layout is evaluated
+                */
+            onBeginLayoutObservable: BABYLON.Observable<AdvancedDynamicTexture>;
+            /**
+                * BABYLON.Observable event triggered after the layout was evaluated
+                */
+            onEndLayoutObservable: BABYLON.Observable<AdvancedDynamicTexture>;
+            /**
+                * BABYLON.Observable event triggered before the texture is rendered
+                */
+            onBeginRenderObservable: BABYLON.Observable<AdvancedDynamicTexture>;
+            /**
+                * BABYLON.Observable event triggered after the texture was rendered
+                */
+            onEndRenderObservable: BABYLON.Observable<AdvancedDynamicTexture>;
+            /**
                 * Gets or sets a boolean defining if alpha is stored as premultiplied
                 */
             premulAlpha: boolean;
@@ -3451,6 +3564,47 @@ declare module BABYLON.GUI {
 }
 declare module BABYLON.GUI {
     /**
+        * This class can be used to get instrumentation data from a AdvancedDynamicTexture object
+        */
+    export class AdvancedDynamicTextureInstrumentation implements BABYLON.IDisposable {
+            /**
+                * Define the instrumented AdvancedDynamicTexture.
+                */
+            texture: AdvancedDynamicTexture;
+            /**
+                * Gets the perf counter used to capture render time
+                */
+            readonly renderTimeCounter: BABYLON.PerfCounter;
+            /**
+                * Gets the perf counter used to capture layout time
+                */
+            readonly layoutTimeCounter: BABYLON.PerfCounter;
+            /**
+                * Enable or disable the render time capture
+                */
+            captureRenderTime: boolean;
+            /**
+                * Enable or disable the layout time capture
+                */
+            captureLayoutTime: boolean;
+            /**
+                * Instantiates a new advanced dynamic texture instrumentation.
+                * This class can be used to get instrumentation data from an AdvancedDynamicTexture object
+                * @param texture Defines the AdvancedDynamicTexture to instrument
+                */
+            constructor(
+            /**
+                * Define the instrumented AdvancedDynamicTexture.
+                */
+            texture: AdvancedDynamicTexture);
+            /**
+                * Dispose and release associated resources.
+                */
+            dispose(): void;
+    }
+}
+declare module BABYLON.GUI {
+    /**
         * Class used to transport BABYLON.Vector2 information for pointer events
         */
     export class Vector2WithInfo extends BABYLON.Vector2 {
@@ -5257,6 +5411,14 @@ declare module BABYLON.GUI {
      */
     export class ScrollViewer extends Rectangle {
             /**
+                * Gets the horizontal scrollbar
+                */
+            readonly horizontalBar: ScrollBar;
+            /**
+                * Gets the vertical scrollbar
+                */
+            readonly verticalBar: ScrollBar;
+            /**
                 * Adds a new control to the current container
                 * @param control defines the control to add
                 * @returns the current container
@@ -6175,4 +6337,27 @@ declare module BABYLON.GUI {
             getClassName(): string;
             static Parse(source: any, scene: BABYLON.Scene, rootUrl: string): FluentMaterial;
     }
+}
+declare module BABYLON.GUI {
+    /**
+        * Class used to create slider controls
+        */
+    export class ScrollBar extends BaseSlider {
+            name?: string | undefined;
+            /** Gets or sets border color */
+            borderColor: string;
+            /** Gets or sets background color */
+            background: string;
+            /**
+                * Creates a new Slider
+                * @param name defines the control name
+                */
+            constructor(name?: string | undefined);
+            protected _getTypeName(): string;
+            protected _getThumbThickness(): number;
+            _draw(context: CanvasRenderingContext2D): void;
+            /** @hidden */
+            protected _updateValueFromPointer(x: number, y: number): void;
+            _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
+    }
 }

+ 2 - 2
dist/preview release/gui/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-gui",
     "description": "The Babylon.js GUI library is an extension you can use to generate interactive user interface. It is build on top of the DynamicTexture.",
-    "version": "4.0.0-alpha.11",
+    "version": "4.0.0-alpha.14",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.11"
+        "babylonjs": "4.0.0-alpha.14"
     },
     "engines": {
         "node": "*"

Різницю між файлами не показано, бо вона завелика
+ 7 - 7
dist/preview release/inspector/babylon.inspector.bundle.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js.map


+ 5 - 5
dist/preview release/inspector/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-inspector",
     "description": "The Babylon.js inspector.",
-    "version": "4.0.0-alpha.11",
+    "version": "4.0.0-alpha.14",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,10 +28,10 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.11",
-        "babylonjs-gui": "4.0.0-alpha.11",
-        "babylonjs-loaders": "4.0.0-alpha.11",
-        "babylonjs-serializers": "4.0.0-alpha.11"
+        "babylonjs": "4.0.0-alpha.14",
+        "babylonjs-gui": "4.0.0-alpha.14",
+        "babylonjs-loaders": "4.0.0-alpha.14",
+        "babylonjs-serializers": "4.0.0-alpha.14"
     },
     "engines": {
         "node": "*"

+ 3 - 3
dist/preview release/loaders/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-loaders",
     "description": "The Babylon.js file loaders library is an extension you can use to load different 3D file types into a Babylon scene.",
-    "version": "4.0.0-alpha.11",
+    "version": "4.0.0-alpha.14",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,8 +27,8 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs-gltf2interface": "4.0.0-alpha.11",
-        "babylonjs": "4.0.0-alpha.11"
+        "babylonjs-gltf2interface": "4.0.0-alpha.14",
+        "babylonjs": "4.0.0-alpha.14"
     },
     "engines": {
         "node": "*"

+ 106 - 0
dist/preview release/materialsLibrary/babylon.skyMaterial.d.ts

@@ -1,29 +1,135 @@
 
 declare module BABYLON {
+    /**
+     * This is the sky material which allows to create dynamic and texture free effects for skyboxes.
+     * @see https://doc.babylonjs.com/extensions/sky
+     */
     class SkyMaterial extends PushMaterial {
+        /**
+         * Defines the overall luminance of sky in interval ]0, 1[.
+         */
         luminance: number;
+        /**
+         * Defines the amount (scattering) of haze as opposed to molecules in atmosphere.
+         */
         turbidity: number;
+        /**
+         * Defines the sky appearance (light intensity).
+         */
         rayleigh: number;
+        /**
+         * Defines the mieCoefficient in interval [0, 0.1] which affects the property .mieDirectionalG.
+         */
         mieCoefficient: number;
+        /**
+         * Defines the amount of haze particles following the Mie scattering theory.
+         */
         mieDirectionalG: number;
+        /**
+         * Defines the distance of the sun according to the active scene camera.
+         */
         distance: number;
+        /**
+         * Defines the sun inclination, in interval [-0.5, 0.5]. When the inclination is not 0, the sun is said
+         * "inclined".
+         */
         inclination: number;
+        /**
+         * Defines the solar azimuth in interval [0, 1]. The azimuth is the angle in the horizontal plan between
+         * an object direction and a reference direction.
+         */
         azimuth: number;
+        /**
+         * Defines the sun position in the sky on (x,y,z). If the property .useSunPosition is set to false, then
+         * the property is overriden by the inclination and the azimuth and can be read at any moment.
+         */
         sunPosition: Vector3;
+        /**
+         * Defines if the sun position should be computed (inclination and azimuth) according to the given
+         * .sunPosition property.
+         */
         useSunPosition: boolean;
+        /**
+         * Defines an offset vector used to get a horizon offset.
+         * @example skyMaterial.cameraOffset.y = camera.globalPosition.y // Set horizon relative to 0 on the Y axis
+         */
+        cameraOffset: Vector3;
         private _cameraPosition;
         private _renderId;
+        /**
+         * Instantiates a new sky material.
+         * This material allows to create dynamic and texture free
+         * effects for skyboxes by taking care of the atmosphere state.
+         * @see https://doc.babylonjs.com/extensions/sky
+         * @param name Define the name of the material in the scene
+         * @param scene Define the scene the material belong to
+         */
         constructor(name: string, scene: Scene);
+        /**
+         * Specifies if the material will require alpha blending
+         * @returns a boolean specifying if alpha blending is needed
+         */
         needAlphaBlending(): boolean;
+        /**
+         * Specifies if this material should be rendered in alpha test mode
+         * @returns false as the sky material doesn't need alpha testing.
+         */
         needAlphaTesting(): boolean;
+        /**
+         * Get the texture used for alpha test purpose.
+         * @returns null as the sky material has no texture.
+         */
         getAlphaTestTexture(): Nullable<BaseTexture>;
+        /**
+         * Get if the submesh is ready to be used and all its information available.
+         * Child classes can use it to update shaders
+         * @param mesh defines the mesh to check
+         * @param subMesh defines which submesh to check
+         * @param useInstances specifies that instances should be used
+         * @returns a boolean indicating that the submesh is ready or not
+         */
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        /**
+         * Binds the submesh to this material by preparing the effect and shader to draw
+         * @param world defines the world transformation matrix
+         * @param mesh defines the mesh containing the submesh
+         * @param subMesh defines the submesh to bind the material to
+         */
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
+        /**
+         * Get the list of animatables in the material.
+         * @returns the list of animatables object used in the material
+         */
         getAnimatables(): IAnimatable[];
+        /**
+         * Disposes the material
+         * @param forceDisposeEffect specifies if effects should be forcefully disposed
+         */
         dispose(forceDisposeEffect?: boolean): void;
+        /**
+         * Makes a duplicate of the material, and gives it a new name
+         * @param name defines the new name for the duplicated material
+         * @returns the cloned material
+         */
         clone(name: string): SkyMaterial;
+        /**
+         * Serializes this material in a JSON representation
+         * @returns the serialized material object
+         */
         serialize(): any;
+        /**
+         * Gets the current class name of the material e.g. "SkyMaterial"
+         * Mainly use in serialization.
+         * @returns the class name
+         */
         getClassName(): string;
+        /**
+         * Creates a sky material from parsed material data
+         * @param source defines the JSON representation of the material
+         * @param scene defines the hosting scene
+         * @param rootUrl defines the root URL to use to load textures and relative dependencies
+         * @returns a new sky material
+         */
         static Parse(source: any, scene: Scene, rootUrl: string): SkyMaterial;
     }
 }

Різницю між файлами не показано, бо вона завелика
+ 113 - 6
dist/preview release/materialsLibrary/babylon.skyMaterial.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/materialsLibrary/babylon.skyMaterial.min.js


+ 106 - 0
dist/preview release/materialsLibrary/babylonjs.materials.d.ts

@@ -475,30 +475,136 @@ declare module BABYLON {
 
 
 declare module BABYLON {
+    /**
+     * This is the sky material which allows to create dynamic and texture free effects for skyboxes.
+     * @see https://doc.babylonjs.com/extensions/sky
+     */
     class SkyMaterial extends PushMaterial {
+        /**
+         * Defines the overall luminance of sky in interval ]0, 1[.
+         */
         luminance: number;
+        /**
+         * Defines the amount (scattering) of haze as opposed to molecules in atmosphere.
+         */
         turbidity: number;
+        /**
+         * Defines the sky appearance (light intensity).
+         */
         rayleigh: number;
+        /**
+         * Defines the mieCoefficient in interval [0, 0.1] which affects the property .mieDirectionalG.
+         */
         mieCoefficient: number;
+        /**
+         * Defines the amount of haze particles following the Mie scattering theory.
+         */
         mieDirectionalG: number;
+        /**
+         * Defines the distance of the sun according to the active scene camera.
+         */
         distance: number;
+        /**
+         * Defines the sun inclination, in interval [-0.5, 0.5]. When the inclination is not 0, the sun is said
+         * "inclined".
+         */
         inclination: number;
+        /**
+         * Defines the solar azimuth in interval [0, 1]. The azimuth is the angle in the horizontal plan between
+         * an object direction and a reference direction.
+         */
         azimuth: number;
+        /**
+         * Defines the sun position in the sky on (x,y,z). If the property .useSunPosition is set to false, then
+         * the property is overriden by the inclination and the azimuth and can be read at any moment.
+         */
         sunPosition: Vector3;
+        /**
+         * Defines if the sun position should be computed (inclination and azimuth) according to the given
+         * .sunPosition property.
+         */
         useSunPosition: boolean;
+        /**
+         * Defines an offset vector used to get a horizon offset.
+         * @example skyMaterial.cameraOffset.y = camera.globalPosition.y // Set horizon relative to 0 on the Y axis
+         */
+        cameraOffset: Vector3;
         private _cameraPosition;
         private _renderId;
+        /**
+         * Instantiates a new sky material.
+         * This material allows to create dynamic and texture free
+         * effects for skyboxes by taking care of the atmosphere state.
+         * @see https://doc.babylonjs.com/extensions/sky
+         * @param name Define the name of the material in the scene
+         * @param scene Define the scene the material belong to
+         */
         constructor(name: string, scene: Scene);
+        /**
+         * Specifies if the material will require alpha blending
+         * @returns a boolean specifying if alpha blending is needed
+         */
         needAlphaBlending(): boolean;
+        /**
+         * Specifies if this material should be rendered in alpha test mode
+         * @returns false as the sky material doesn't need alpha testing.
+         */
         needAlphaTesting(): boolean;
+        /**
+         * Get the texture used for alpha test purpose.
+         * @returns null as the sky material has no texture.
+         */
         getAlphaTestTexture(): Nullable<BaseTexture>;
+        /**
+         * Get if the submesh is ready to be used and all its information available.
+         * Child classes can use it to update shaders
+         * @param mesh defines the mesh to check
+         * @param subMesh defines which submesh to check
+         * @param useInstances specifies that instances should be used
+         * @returns a boolean indicating that the submesh is ready or not
+         */
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        /**
+         * Binds the submesh to this material by preparing the effect and shader to draw
+         * @param world defines the world transformation matrix
+         * @param mesh defines the mesh containing the submesh
+         * @param subMesh defines the submesh to bind the material to
+         */
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
+        /**
+         * Get the list of animatables in the material.
+         * @returns the list of animatables object used in the material
+         */
         getAnimatables(): IAnimatable[];
+        /**
+         * Disposes the material
+         * @param forceDisposeEffect specifies if effects should be forcefully disposed
+         */
         dispose(forceDisposeEffect?: boolean): void;
+        /**
+         * Makes a duplicate of the material, and gives it a new name
+         * @param name defines the new name for the duplicated material
+         * @returns the cloned material
+         */
         clone(name: string): SkyMaterial;
+        /**
+         * Serializes this material in a JSON representation
+         * @returns the serialized material object
+         */
         serialize(): any;
+        /**
+         * Gets the current class name of the material e.g. "SkyMaterial"
+         * Mainly use in serialization.
+         * @returns the class name
+         */
         getClassName(): string;
+        /**
+         * Creates a sky material from parsed material data
+         * @param source defines the JSON representation of the material
+         * @param scene defines the hosting scene
+         * @param rootUrl defines the root URL to use to load textures and relative dependencies
+         * @returns a new sky material
+         */
         static Parse(source: any, scene: Scene, rootUrl: string): SkyMaterial;
     }
 }

Різницю між файлами не показано, бо вона завелика
+ 113 - 6
dist/preview release/materialsLibrary/babylonjs.materials.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/materialsLibrary/babylonjs.materials.min.js


+ 106 - 0
dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts

@@ -480,30 +480,136 @@ declare module BABYLON {
 
 
 declare module BABYLON {
+    /**
+     * This is the sky material which allows to create dynamic and texture free effects for skyboxes.
+     * @see https://doc.babylonjs.com/extensions/sky
+     */
     class SkyMaterial extends PushMaterial {
+        /**
+         * Defines the overall luminance of sky in interval ]0, 1[.
+         */
         luminance: number;
+        /**
+         * Defines the amount (scattering) of haze as opposed to molecules in atmosphere.
+         */
         turbidity: number;
+        /**
+         * Defines the sky appearance (light intensity).
+         */
         rayleigh: number;
+        /**
+         * Defines the mieCoefficient in interval [0, 0.1] which affects the property .mieDirectionalG.
+         */
         mieCoefficient: number;
+        /**
+         * Defines the amount of haze particles following the Mie scattering theory.
+         */
         mieDirectionalG: number;
+        /**
+         * Defines the distance of the sun according to the active scene camera.
+         */
         distance: number;
+        /**
+         * Defines the sun inclination, in interval [-0.5, 0.5]. When the inclination is not 0, the sun is said
+         * "inclined".
+         */
         inclination: number;
+        /**
+         * Defines the solar azimuth in interval [0, 1]. The azimuth is the angle in the horizontal plan between
+         * an object direction and a reference direction.
+         */
         azimuth: number;
+        /**
+         * Defines the sun position in the sky on (x,y,z). If the property .useSunPosition is set to false, then
+         * the property is overriden by the inclination and the azimuth and can be read at any moment.
+         */
         sunPosition: Vector3;
+        /**
+         * Defines if the sun position should be computed (inclination and azimuth) according to the given
+         * .sunPosition property.
+         */
         useSunPosition: boolean;
+        /**
+         * Defines an offset vector used to get a horizon offset.
+         * @example skyMaterial.cameraOffset.y = camera.globalPosition.y // Set horizon relative to 0 on the Y axis
+         */
+        cameraOffset: Vector3;
         private _cameraPosition;
         private _renderId;
+        /**
+         * Instantiates a new sky material.
+         * This material allows to create dynamic and texture free
+         * effects for skyboxes by taking care of the atmosphere state.
+         * @see https://doc.babylonjs.com/extensions/sky
+         * @param name Define the name of the material in the scene
+         * @param scene Define the scene the material belong to
+         */
         constructor(name: string, scene: Scene);
+        /**
+         * Specifies if the material will require alpha blending
+         * @returns a boolean specifying if alpha blending is needed
+         */
         needAlphaBlending(): boolean;
+        /**
+         * Specifies if this material should be rendered in alpha test mode
+         * @returns false as the sky material doesn't need alpha testing.
+         */
         needAlphaTesting(): boolean;
+        /**
+         * Get the texture used for alpha test purpose.
+         * @returns null as the sky material has no texture.
+         */
         getAlphaTestTexture(): Nullable<BaseTexture>;
+        /**
+         * Get if the submesh is ready to be used and all its information available.
+         * Child classes can use it to update shaders
+         * @param mesh defines the mesh to check
+         * @param subMesh defines which submesh to check
+         * @param useInstances specifies that instances should be used
+         * @returns a boolean indicating that the submesh is ready or not
+         */
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
+        /**
+         * Binds the submesh to this material by preparing the effect and shader to draw
+         * @param world defines the world transformation matrix
+         * @param mesh defines the mesh containing the submesh
+         * @param subMesh defines the submesh to bind the material to
+         */
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
+        /**
+         * Get the list of animatables in the material.
+         * @returns the list of animatables object used in the material
+         */
         getAnimatables(): IAnimatable[];
+        /**
+         * Disposes the material
+         * @param forceDisposeEffect specifies if effects should be forcefully disposed
+         */
         dispose(forceDisposeEffect?: boolean): void;
+        /**
+         * Makes a duplicate of the material, and gives it a new name
+         * @param name defines the new name for the duplicated material
+         * @returns the cloned material
+         */
         clone(name: string): SkyMaterial;
+        /**
+         * Serializes this material in a JSON representation
+         * @returns the serialized material object
+         */
         serialize(): any;
+        /**
+         * Gets the current class name of the material e.g. "SkyMaterial"
+         * Mainly use in serialization.
+         * @returns the class name
+         */
         getClassName(): string;
+        /**
+         * Creates a sky material from parsed material data
+         * @param source defines the JSON representation of the material
+         * @param scene defines the hosting scene
+         * @param rootUrl defines the root URL to use to load textures and relative dependencies
+         * @returns a new sky material
+         */
         static Parse(source: any, scene: Scene, rootUrl: string): SkyMaterial;
     }
 }

+ 2 - 2
dist/preview release/materialsLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-materials",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.0.0-alpha.11",
+    "version": "4.0.0-alpha.14",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.11"
+        "babylonjs": "4.0.0-alpha.14"
     },
     "engines": {
         "node": "*"

+ 2 - 2
dist/preview release/postProcessesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-post-process",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.0.0-alpha.11",
+    "version": "4.0.0-alpha.14",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.11"
+        "babylonjs": "4.0.0-alpha.14"
     },
     "engines": {
         "node": "*"

+ 2 - 2
dist/preview release/proceduralTexturesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-procedural-textures",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.0.0-alpha.11",
+    "version": "4.0.0-alpha.14",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.11"
+        "babylonjs": "4.0.0-alpha.14"
     },
     "engines": {
         "node": "*"

+ 3 - 3
dist/preview release/serializers/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-serializers",
     "description": "The Babylon.js serializers library is an extension you can use to serialize Babylon scenes.",
-    "version": "4.0.0-alpha.11",
+    "version": "4.0.0-alpha.14",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,8 +27,8 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.11",
-        "babylonjs-gltf2interface": "4.0.0-alpha.11"
+        "babylonjs": "4.0.0-alpha.14",
+        "babylonjs-gltf2interface": "4.0.0-alpha.14"
     },
     "engines": {
         "node": "*"

+ 1 - 15
dist/preview release/viewer/babylon.viewer.d.ts

@@ -924,7 +924,7 @@ declare module BabylonViewer {
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 declare module BabylonViewer {
@@ -1558,20 +1558,6 @@ declare module BabylonViewer {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 declare module BabylonViewer {
-    /**
-        * A custom upgrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedUpgrade(sceneManager: SceneManager): boolean;
-    /**
-        * A custom degrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedDegrade(sceneManager: SceneManager): boolean;
-}
-declare module BabylonViewer {
 }
 declare module BabylonViewer {
     export interface IEnvironmentMapConfiguration {

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


Різницю між файлами не показано, бо вона завелика
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


+ 1 - 18
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -985,14 +985,13 @@ declare module 'babylonjs-viewer/templating/viewerTemplatePlugin' {
 }
 
 declare module 'babylonjs-viewer/optimizer/custom' {
-    import { extendedUpgrade } from "babylonjs-viewer/optimizer/custom/extended";
     import { SceneManager } from "babylonjs-viewer/managers/sceneManager";
     /**
       *
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 
@@ -1663,22 +1662,6 @@ declare module 'babylonjs-viewer/loader/plugins' {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 
-declare module 'babylonjs-viewer/optimizer/custom/extended' {
-    import { SceneManager } from 'babylonjs-viewer/managers/sceneManager';
-    /**
-        * A custom upgrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedUpgrade(sceneManager: SceneManager): boolean;
-    /**
-        * A custom degrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedDegrade(sceneManager: SceneManager): boolean;
-}
-
 declare module 'babylonjs-viewer/configuration/interfaces' {
     export * from 'babylonjs-viewer/configuration/interfaces/cameraConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/colorGradingConfiguration';

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

@@ -2,6 +2,7 @@
 
 ## Major updates
 
+- New [fancy forum](https://forum.babylonjs.com)!! ([Deltakosh](https://github.com/deltakosh))
 - [Inspector v2.0](https://doc.babylonjs.com/features/playground_debuglayer). [Dev log](https://medium.com/@babylonjs/dev-log-creating-the-new-inspector-b15c50900205) ([Deltakosh](https://github.com/deltakosh))
 - Added support for [parallel shader compilation](https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/) ([Deltakosh](https://github.com/deltakosh))
 - Added [Object Based Motion Blur](http://doc.babylonjs.com/how_to/using_motionblurpostprocess) post-process ([julien-moreau](https://github.com/julien-moreau))
@@ -58,6 +59,7 @@
   - Enabled a removal in O(1) from the `transformNodes` array and `materials` array of the `Scene`. As a consequence, the order of the element within these arrays might change during a removal
   - Enabled a removal in O(1) from the `instances` array of a `Mesh`. As a consequence, the order of the element within this array might change during a removal
   - Stopped calling `Array.splice` on the `scene.meshes` array and on the `engine._uniformBuffer` when removing an element. As a consequence, the order of the element within these arrays might change during a removal
+  - Added an option `useGeometryUniqueIdsMap` in the `Scene` constructor options. When set to true, each `Scene` isntance will have and will keep up-to-date a map of geometry per `uniqueId`. This is to avoid browsing all the geometries of the scene when a new one is being pushed. It also enables a removal of geometry in O(1). Disabled by default
   - Added an option `useMaterialMeshMap` in the `Scene` constructor options. When set to true, each `Material` isntance will have and will keep up-to-date a map of its bound meshes. This is to avoid browsing all the meshes of the scene to retrieve the ones bound to the current material when disposing the Material. Disabled by default
   - Added an option `useClonedMeshhMap` in the `Scene` constructor options. When set to true, each `Mesh` will have and will keep up-to-date a map of cloned meshes. This is to avoid browsing all the meshes of the scene to retrieve the ones that have the current mesh as source mesh. Disabled by default
   - Added `blockfreeActiveMeshesAndRenderingGroups` property in the `Scene`, following the same model as `blockMaterialDirtyMechanism`. This is to avoid calling `Scene.freeActiveMeshes` and `Scene.freeRenderingGroups` for each disposed mesh when we dispose several meshes in a row. One have to set `blockfreeActiveMeshesAndRenderingGroups` to `true` just before disposing the meshes, and set it back to `false` just after
@@ -84,6 +86,7 @@
 - Invert vScale of compressed ktx textures as they are inverted in the file and UNPACK_FLIP_Y_WEBGL is not supported by ktx ([TrevorDev](https://github.com/TrevorDev))
 - Enable dragging in boundingBoxGizmo without needing a parent ([TrevorDev](https://github.com/TrevorDev))
 - InvalidateRect added to AdvancedDynamicTexture to improve perf for highly populated GUIs ([TrevorDev](https://github.com/TrevorDev))
+- Added per mesh culling strategy ([jerome](https://github.com/jbousquie))
 
 ### glTF Loader
 
@@ -100,6 +103,7 @@
 ### Viewer
 
 ### Materials Library
+- Added the `cameraOffset` vector property in the `SkyMaterial` to get an offset according to the horizon ([julien-moreau](https://github.com/julien-moreau))
 
 ## Bug fixes
 - Fixed TransformNode.setDirection (orientation was wrong) ([Deltakosh](https://github.com/deltakosh))
@@ -124,6 +128,8 @@
 - SixDofDragBehavior will support when the camera is parented ([TrevorDev](https://github.com/TrevorDev))
 - Deactivate webvr lasers when not in vr ([TrevorDev](https://github.com/TrevorDev))
 - Update physics position using absolutePosition instead of pivotPosition ([TrevorDev](https://github.com/TrevorDev))
+- Disable camera arrow key controls when the Command key is selected on Mac OS ([kcoley](https://github.com/kcoley))
+- Viewer should not set receiveShadows on an instanced mesh ([TrevorDev](https://github.com/TrevorDev))
 
 ### Core Engine
 - Fixed a bug with `mesh.alwaysSelectAsActiveMesh` preventing layerMask to be taken in account ([Deltakosh](https://github.com/deltakosh))
@@ -141,6 +147,9 @@
 - Fixed infiniteDistance not working anymore ([Sebavan](https://github.com/Sebavan))
 - Fixed bug in SolidParticle BoundingSphere update within the SolidParticleSystem ([barroij](https://github.com/barroij))
 - Update Picking so that when the picked Mesh is a LinesMesh, the index of the picked line is returned in the `faceId` property of the `PickingInfo`, as we do with face index the picked Mesh is made of triangle faces ([barroij](https://github.com/barroij))
+- Do not clone mesh observables ([Sebavan](https://github.com/Sebavan))
+- Fixed Inspector resolution with AMD loader ([Sebavan](https://github.com/Sebavan))
+- Fix a bug when a call to `updateIndices` leads to changing the size of the index buffer by recreating the subMeshes in that case ([barroij](https://github.com/barroij))
 
 ### Viewer
 

+ 122 - 0
gui/src/2D/adtInstrumentation.ts

@@ -0,0 +1,122 @@
+import { IDisposable, PerfCounter, Nullable, Observer } from "babylonjs";
+import { AdvancedDynamicTexture } from "./advancedDynamicTexture";
+
+/**
+ * This class can be used to get instrumentation data from a AdvancedDynamicTexture object
+ */
+export class AdvancedDynamicTextureInstrumentation implements IDisposable {
+    private _captureRenderTime = false;
+    private _renderTime = new PerfCounter();
+
+    private _captureLayoutTime = false;
+    private _layoutTime = new PerfCounter();
+
+    // Observers
+    private _onBeginRenderObserver: Nullable<Observer<AdvancedDynamicTexture>> = null;
+    private _onEndRenderObserver: Nullable<Observer<AdvancedDynamicTexture>> = null;
+    private _onBeginLayoutObserver: Nullable<Observer<AdvancedDynamicTexture>> = null;
+    private _onEndLayoutObserver: Nullable<Observer<AdvancedDynamicTexture>> = null;
+
+    // Properties
+
+    /**
+     * Gets the perf counter used to capture render time
+     */
+    public get renderTimeCounter(): PerfCounter {
+        return this._renderTime;
+    }
+
+    /**
+     * Gets the perf counter used to capture layout time
+     */
+    public get layoutTimeCounter(): PerfCounter {
+        return this._layoutTime;
+    }
+
+    /**
+     * Enable or disable the render time capture
+     */
+    public get captureRenderTime(): boolean {
+        return this._captureRenderTime;
+    }
+
+    public set captureRenderTime(value: boolean) {
+        if (value === this._captureRenderTime) {
+            return;
+        }
+
+        this._captureRenderTime = value;
+
+        if (value) {
+            this._onBeginRenderObserver = this.texture.onBeginRenderObservable.add(() => {
+                this._renderTime.beginMonitoring();
+            });
+
+            this._onEndRenderObserver = this.texture.onEndRenderObservable.add(() => {
+                this._renderTime.endMonitoring(true);
+            });
+        } else {
+            this.texture.onBeginRenderObservable.remove(this._onBeginRenderObserver);
+            this._onBeginRenderObserver = null;
+            this.texture.onEndRenderObservable.remove(this._onEndRenderObserver);
+            this._onEndRenderObserver = null;
+        }
+    }
+
+    /**
+     * Enable or disable the layout time capture
+     */
+    public get captureLayoutTime(): boolean {
+        return this._captureLayoutTime;
+    }
+
+    public set captureLayoutTime(value: boolean) {
+        if (value === this._captureLayoutTime) {
+            return;
+        }
+
+        this._captureLayoutTime = value;
+
+        if (value) {
+            this._onBeginLayoutObserver = this.texture.onBeginLayoutObservable.add(() => {
+                this._layoutTime.beginMonitoring();
+            });
+
+            this._onEndLayoutObserver = this.texture.onEndLayoutObservable.add(() => {
+                this._layoutTime.endMonitoring(true);
+            });
+        } else {
+            this.texture.onBeginLayoutObservable.remove(this._onBeginLayoutObserver);
+            this._onBeginLayoutObserver = null;
+            this.texture.onEndLayoutObservable.remove(this._onEndLayoutObserver);
+            this._onEndLayoutObserver = null;
+        }
+    }
+    /**
+     * Instantiates a new advanced dynamic texture instrumentation.
+     * This class can be used to get instrumentation data from an AdvancedDynamicTexture object
+     * @param texture Defines the AdvancedDynamicTexture to instrument
+     */
+    public constructor(
+        /**
+         * Define the instrumented AdvancedDynamicTexture.
+         */
+        public texture: AdvancedDynamicTexture) {
+    }
+
+    /**
+     * Dispose and release associated resources.
+     */
+    public dispose() {
+        this.texture.onBeginRenderObservable.remove(this._onBeginRenderObserver);
+        this._onBeginRenderObserver = null;
+        this.texture.onEndRenderObservable.remove(this._onEndRenderObserver);
+        this._onEndRenderObserver = null;
+        this.texture.onBeginLayoutObservable.remove(this._onBeginLayoutObserver);
+        this._onBeginLayoutObserver = null;
+        this.texture.onEndLayoutObservable.remove(this._onEndLayoutObserver);
+        this._onEndLayoutObserver = null;
+
+        (<any>this.texture) = null;
+    }
+}

Різницю між файлами не показано, бо вона завелика
+ 970 - 941
gui/src/2D/advancedDynamicTexture.ts


+ 2 - 2
gui/src/2D/controls/container.ts

@@ -426,8 +426,8 @@ export class Container extends Control {
     public dispose() {
         super.dispose();
 
-        for (var control of this._children) {
-            control.dispose();
+        for (var index = this.children.length - 1; index >= 0; index--) {
+            this.children[index].dispose();
         }
     }
 }

+ 3 - 0
gui/src/2D/controls/grid.ts

@@ -291,6 +291,7 @@ export class Grid extends Container {
         goodContainer.addControl(control);
         this._childControls.push(control);
         control._tag = key;
+        control.parent = this;
 
         this._markAsDirty();
 
@@ -467,5 +468,7 @@ export class Grid extends Container {
         for (var control of this._childControls) {
             control.dispose();
         }
+
+        this._childControls = [];
     }
 }

+ 27 - 0
gui/src/2D/controls/scrollViewers/scrollViewer.ts

@@ -30,6 +30,20 @@ export class ScrollViewer extends Rectangle {
     private _clientHeight: number;
 
     /**
+     * Gets the horizontal scrollbar
+     */
+    public get horizontalBar(): ScrollBar {
+        return this._horizontalBar;
+    }
+
+    /**
+     * Gets the vertical scrollbar
+     */
+    public get verticalBar(): ScrollBar {
+        return this._verticalBar;
+    }
+
+    /**
      * Adds a new control to the current container
      * @param control defines the control to add
      * @returns the current container
@@ -294,6 +308,19 @@ export class ScrollViewer extends Rectangle {
         this._endLeft = this._clientWidth - windowContentsWidth;
         this._endTop = this._clientHeight - windowContentsHeight;
 
+        const newLeft = this._horizontalBar.value * this._endLeft + "px";
+        const newTop = this._verticalBar.value * this._endTop + "px";
+
+        if (newLeft !== this._window.left) {
+            this._window.left = newLeft;
+            this._rebuildLayout = true;
+        }
+
+        if (newTop !== this._window.top) {
+            this._window.top = newTop;
+            this._rebuildLayout = true;
+        }
+
         let horizontalMultiplicator = this._clientWidth / windowContentsWidth;
         let verticalMultiplicator = this._clientHeight / windowContentsHeight;
 

+ 1 - 0
gui/src/2D/index.ts

@@ -1,6 +1,7 @@
 export * from "./controls";
 
 export * from "./advancedDynamicTexture";
+export * from "./adtInstrumentation";
 export * from "./math2D";
 export * from "./measure";
 export * from "./multiLinePoint";

+ 16 - 4
inspector/src/components/actionTabs/actionTabs.scss

@@ -19,6 +19,10 @@
     font: 14px "Arial";    
     overflow: hidden;
 
+    .hoverIcon:hover {
+        opacity: 0.8;
+    }
+
     #header {
         height: 30px;
         font-size: 16px;
@@ -220,7 +224,7 @@
                         opacity: 0.8;
                         margin:5px;
                         margin-top: 6px;
-                        max-width: 200px;
+                        max-width: 140px;
                         text-decoration: underline;
                         cursor: pointer;
                     }
@@ -690,7 +694,7 @@
                     .firstLine {
                         height: 30px;
                         display: grid;
-                        grid-template-columns: 1fr auto 20px;
+                        grid-template-columns: 1fr auto 20px 20px;
 
                         .label {
                             grid-column: 1;
@@ -706,7 +710,7 @@
 
                             input[type="color"] {
                                 -webkit-appearance: none;
-                                border: none;
+                                border: 1px solid rgba(255, 255, 255, 0.5);
                                 padding: 0;
                                 width: 30px;
                                 height: 20px;
@@ -723,13 +727,21 @@
                             }
                         }
 
-                        .expand {
+                        .copy {
                             grid-column: 3;
                             display: grid;
                             align-items: center;
                             justify-items: center;
                             cursor: pointer;
                         }
+
+                        .expand {
+                            grid-column: 4;
+                            display: grid;
+                            align-items: center;
+                            justify-items: center;
+                            cursor: pointer;
+                        }
                     }   
 
                     .secondLine {

+ 3 - 2
inspector/src/components/actionTabs/actionTabsComponent.tsx

@@ -73,10 +73,11 @@ export class ActionTabsComponent extends React.Component<IActionTabsComponentPro
             <TabsComponent selectedIndex={this.state.selectedIndex} onSelectedIndexChange={(value) => this.changeSelectedTab(value)}>
                 <PropertyGridTabComponent
                     title="Properties" icon={faFileAlt} scene={this.props.scene} selectedEntity={this.state.selectedEntity}
+                    globalState={this.props.globalState}
                     onSelectionChangedObservable={this.props.globalState.onSelectionChangedObservable}
                     onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />
-                <DebugTabComponent title="Debug" icon={faBug} scene={this.props.scene} />
-                <StatisticsTabComponent title="Statistics" icon={faChartBar} scene={this.props.scene} />
+                <DebugTabComponent title="Debug" icon={faBug} scene={this.props.scene} globalState={this.props.globalState} />
+                <StatisticsTabComponent title="Statistics" icon={faChartBar} scene={this.props.scene} globalState={this.props.globalState} />
                 <ToolsTabComponent title="Tools" icon={faWrench} scene={this.props.scene} globalState={this.props.globalState} />
             </TabsComponent>
         )

+ 21 - 2
inspector/src/components/actionTabs/lines/color3LineComponent.tsx

@@ -3,7 +3,7 @@ import { Observable, Color3 } from "babylonjs";
 import { PropertyChangedEvent } from "../../propertyChangedEvent";
 import { NumericInputComponent } from "./numericInputComponent";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { faMinus, faPlus } from "@fortawesome/free-solid-svg-icons";
+import { faMinus, faPlus, faCopy } from "@fortawesome/free-solid-svg-icons";
 
 export interface IColor3LineComponentProps {
     label: string,
@@ -103,6 +103,22 @@ export class Color3LineComponent extends React.Component<IColor3LineComponentPro
         this.raiseOnPropertyChanged(store);
     }
 
+    copyToClipboard() {
+        var element = document.createElement('div');
+        element.textContent = this.state.color.toHexString();
+        document.body.appendChild(element);
+
+        if (window.getSelection) {
+            var range = document.createRange();
+            range.selectNode(element);
+            window.getSelection().removeAllRanges();
+            window.getSelection().addRange(range);
+        }
+
+        document.execCommand('copy');
+        element.remove();
+    }
+
     render() {
 
         const chevron = this.state.isExpanded ? <FontAwesomeIcon icon={faMinus} /> : <FontAwesomeIcon icon={faPlus} />
@@ -117,7 +133,10 @@ export class Color3LineComponent extends React.Component<IColor3LineComponentPro
                     <div className="color3">
                         <input type="color" value={colorAsColor3.toHexString()} onChange={(evt) => this.onChange(evt.target.value)} />
                     </div>
-                    <div className="expand" onClick={() => this.switchExpandState()}>
+                    <div className="copy hoverIcon" onClick={() => this.copyToClipboard()} title="Copy to clipboard">
+                        <FontAwesomeIcon icon={faCopy} />
+                    </div>
+                    <div className="expand hoverIcon" onClick={() => this.switchExpandState()} title="Expand">
                         {chevron}
                     </div>
                 </div>

+ 1 - 1
inspector/src/components/actionTabs/lines/floatLineComponent.tsx

@@ -109,7 +109,7 @@ export class FloatLineComponent extends React.Component<IFloatLineComponentProps
                     {this.props.label}
                 </div>
                 <div className="value">
-                    <input className="numeric-input" value={this.state.value} onBlur={() => this.unlock()} onFocus={() => this.lock()} onChange={evt => this.updateValue(evt.target.value)} />
+                    <input type="number" step="0.01" className="numeric-input" value={this.state.value} onBlur={() => this.unlock()} onFocus={() => this.lock()} onChange={evt => this.updateValue(evt.target.value)} />
                 </div>
             </div>
         );

+ 1 - 1
inspector/src/components/actionTabs/lines/numericInputComponent.tsx

@@ -56,7 +56,7 @@ export class NumericInputComponent extends React.Component<INumericInputComponen
                         {`${this.props.label}: `}
                     </div>
                 }
-                <input className="numeric-input" value={this.state.value} onChange={evt => this.updateValue(evt)} />
+                <input type="number" step="1" className="numeric-input" value={this.state.value} onChange={evt => this.updateValue(evt)} />
             </div>
         )
     }

+ 7 - 3
inspector/src/components/actionTabs/lines/textureLineComponent.tsx

@@ -1,10 +1,12 @@
 import * as React from "react";
 import { BaseTexture, PostProcess, Texture } from "babylonjs";
+import { GlobalState } from "components/globalState";
 
 interface ITextureLineComponentProps {
     texture: BaseTexture,
     width: number,
-    height: number
+    height: number,
+    globalState: GlobalState
 }
 
 export class TextureLineComponent extends React.Component<ITextureLineComponentProps, { displayRed: boolean, displayGreen: boolean, displayBlue: boolean, displayAlpha: boolean, face: number }> {
@@ -20,8 +22,8 @@ export class TextureLineComponent extends React.Component<ITextureLineComponentP
         }
     }
 
-    shouldComponentUpdate(nextProps: ITextureLineComponentProps): boolean {
-        return (nextProps.texture !== this.props.texture);
+    shouldComponentUpdate(nextProps: ITextureLineComponentProps, nextState: { displayRed: boolean, displayGreen: boolean, displayBlue: boolean, displayAlpha: boolean, face: number }): boolean {
+        return (nextProps.texture !== this.props.texture || nextState.displayRed !== this.state.displayRed || nextState.displayGreen !== this.state.displayGreen || nextState.displayBlue !== this.state.displayBlue || nextState.displayAlpha !== this.state.displayAlpha || nextState.face !== this.state.face);
     }
 
     componentDidMount() {
@@ -63,6 +65,7 @@ export class TextureLineComponent extends React.Component<ITextureLineComponentP
 
         const previewCanvas = this.refs.canvas as HTMLCanvasElement;
 
+        this.props.globalState.blockMutationUpdates = true;
         let rtt = new BABYLON.RenderTargetTexture(
             "temp",
             { width: width, height: height },
@@ -146,6 +149,7 @@ export class TextureLineComponent extends React.Component<ITextureLineComponentP
         passPostProcess.dispose();
 
         previewCanvas.style.height = height + "px";
+        this.props.globalState.blockMutationUpdates = false;
     }
 
     render() {

+ 1 - 1
inspector/src/components/actionTabs/lines/vector3LineComponent.tsx

@@ -100,7 +100,7 @@ export class Vector3LineComponent extends React.Component<IVector3LineComponentP
                         {`X: ${this.state.value.x.toFixed(2)}, Y: ${this.state.value.y.toFixed(2)}, Z: ${this.state.value.z.toFixed(2)}`}
 
                     </div>
-                    <div className="expand" onClick={() => this.switchExpandState()}>
+                    <div className="expand hoverIcon" onClick={() => this.switchExpandState()} title="Expand">
                         {chevron}
                     </div>
                 </div>

+ 1 - 1
inspector/src/components/actionTabs/paneComponent.tsx

@@ -10,7 +10,7 @@ export interface IPaneComponentProps {
     selectedEntity?: any,
     onSelectionChangedObservable?: Observable<any>,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>,
-    globalState?: GlobalState
+    globalState: GlobalState
 }
 
 export class PaneComponent extends React.Component<IPaneComponentProps, { tag: any }> {

+ 22 - 1
inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx

@@ -1,6 +1,6 @@
 import * as React from "react";
 import { PaneComponent, IPaneComponentProps } from "../paneComponent";
-import { Mesh, TransformNode, Material, StandardMaterial, Texture, PBRMaterial, Scene, FreeCamera, ArcRotateCamera, HemisphericLight, PointLight, BackgroundMaterial, AnimationGroup } from "babylonjs";
+import { Mesh, TransformNode, Material, StandardMaterial, Texture, PBRMaterial, Scene, FreeCamera, ArcRotateCamera, HemisphericLight, PointLight, BackgroundMaterial, AnimationGroup, PBRMetallicRoughnessMaterial, PBRSpecularGlossinessMaterial } from "babylonjs";
 import { MaterialPropertyGridComponent } from "./propertyGrids/materials/materialPropertyGridComponent";
 import { StandardMaterialPropertyGridComponent } from "./propertyGrids/materials/standardMaterialPropertyGridComponent";
 import { TexturePropertyGridComponent } from "./propertyGrids/materials/texturePropertyGridComponent";
@@ -33,6 +33,8 @@ import { RadioButtonPropertyGridComponent } from "./propertyGrids/gui/radioButto
 import { LinePropertyGridComponent } from "./propertyGrids/gui/linePropertyGridComponent";
 import { ScrollViewerPropertyGridComponent } from "./propertyGrids/gui/scrollViewerPropertyGridComponent";
 import { GridPropertyGridComponent } from "./propertyGrids/gui/gridPropertyGridComponent";
+import { PBRMetallicRoughnessMaterialPropertyGridComponent } from "./propertyGrids/materials/pbrMetallicRoughnessMaterialPropertyGridComponent";
+import { PBRSpecularGlossinessMaterialPropertyGridComponent } from "./propertyGrids/materials/pbrSpecularGlossinessMaterialPropertyGridComponent";
 
 export class PropertyGridTabComponent extends PaneComponent {
     private _timerIntervalId: number;
@@ -135,6 +137,24 @@ export class PropertyGridTabComponent extends PaneComponent {
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }
 
+            if (className === "PBRMetallicRoughnessMaterial") {
+                const material = entity as PBRMetallicRoughnessMaterial;
+                return (<PBRMetallicRoughnessMaterialPropertyGridComponent
+                    material={material}
+                    lockObject={this._lockObject}
+                    onSelectionChangedObservable={this.props.onSelectionChangedObservable}
+                    onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
+            }
+
+            if (className === "PBRSpecularGlossinessMaterial") {
+                const material = entity as PBRSpecularGlossinessMaterial;
+                return (<PBRSpecularGlossinessMaterialPropertyGridComponent
+                    material={material}
+                    lockObject={this._lockObject}
+                    onSelectionChangedObservable={this.props.onSelectionChangedObservable}
+                    onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
+            }
+
             if (className === "BackgroundMaterial") {
                 const material = entity as BackgroundMaterial;
                 return (<BackgroundMaterialPropertyGridComponent
@@ -163,6 +183,7 @@ export class PropertyGridTabComponent extends PaneComponent {
             if (className.indexOf("Texture") !== -1) {
                 const texture = entity as Texture;
                 return (<TexturePropertyGridComponent texture={texture}
+                    globalState={this.props.globalState}
                     lockObject={this._lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />);
             }

+ 1 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx

@@ -62,6 +62,7 @@ export class PBRMaterialPropertyGridComponent extends React.Component<IPBRMateri
                 <LineContainerComponent title="LEVELS" closed={true}>
                     <SliderLineComponent label="Environment" target={material} propertyName="environmentIntensity" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <SliderLineComponent label="Metallic" target={material} propertyName="metallic" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <SliderLineComponent label="Roughness" target={material} propertyName="roughness" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <SliderLineComponent label="Micro-surface" target={material} propertyName="microSurface" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <SliderLineComponent label="Specular" target={material} propertyName="specularIntensity" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     {

+ 61 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMetallicRoughnessMaterialPropertyGridComponent.tsx

@@ -0,0 +1,61 @@
+import * as React from "react";
+import { Observable, PBRMetallicRoughnessMaterial, BaseTexture } from "babylonjs";
+import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
+import { LineContainerComponent } from "../../../lineContainerComponent";
+import { Color3LineComponent } from "../../../lines/color3LineComponent";
+import { SliderLineComponent } from "../../../lines/sliderLineComponent";
+import { CommonMaterialPropertyGridComponent } from "./commonMaterialPropertyGridComponent";
+import { TextureLinkLineComponent } from "../../../lines/textureLinkLineComponent";
+import { LockObject } from "../lockObject";
+
+interface IPBRMetallicRoughnessMaterialPropertyGridComponentProps {
+    material: PBRMetallicRoughnessMaterial,
+    lockObject: LockObject,
+    onSelectionChangedObservable?: Observable<any>,
+    onPropertyChangedObservable?: Observable<PropertyChangedEvent>
+}
+
+export class PBRMetallicRoughnessMaterialPropertyGridComponent extends React.Component<IPBRMetallicRoughnessMaterialPropertyGridComponentProps> {
+    constructor(props: IPBRMetallicRoughnessMaterialPropertyGridComponentProps) {
+        super(props);
+    }
+
+    renderTextures() {
+        const material = this.props.material;
+
+        if (material.getActiveTextures().length === 0) {
+            return null;
+        }
+
+        const onDebugSelectionChangeObservable = new BABYLON.Observable<BaseTexture>();
+
+        return (
+            <LineContainerComponent title="TEXTURES">
+                <TextureLinkLineComponent label="Base" texture={material.baseTexture} material={material} onSelectionChangedObservable={this.props.onSelectionChangedObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
+                <TextureLinkLineComponent label="Metallic roughness" texture={material.metallicRoughnessTexture} material={material} onSelectionChangedObservable={this.props.onSelectionChangedObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
+                <TextureLinkLineComponent label="Environment" texture={material.environmentTexture} material={material} onSelectionChangedObservable={this.props.onSelectionChangedObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
+                <TextureLinkLineComponent label="Emissive" texture={material.emissiveTexture} material={material} onSelectionChangedObservable={this.props.onSelectionChangedObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
+                <TextureLinkLineComponent label="Lightmap" texture={material.lightmapTexture} material={material} onSelectionChangedObservable={this.props.onSelectionChangedObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
+            </LineContainerComponent>
+        )
+    }
+
+    render() {
+        const material = this.props.material;
+
+        return (
+            <div className="pane">
+                <CommonMaterialPropertyGridComponent lockObject={this.props.lockObject} material={material} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                {this.renderTextures()}
+                <LineContainerComponent title="LIGHTING & COLORS">
+                    <Color3LineComponent label="Base" target={material} propertyName="baseColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <Color3LineComponent label="Emissive" target={material} propertyName="emissiveColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                </LineContainerComponent>
+                <LineContainerComponent title="LEVELS" closed={true}>
+                    <SliderLineComponent label="Metallic" target={material} propertyName="metallic" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <SliderLineComponent label="Roughness" target={material} propertyName="roughness" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                </LineContainerComponent>
+            </div>
+        );
+    }
+}

+ 60 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrSpecularGlossinessMaterialPropertyGridComponent.tsx

@@ -0,0 +1,60 @@
+import * as React from "react";
+import { Observable, PBRSpecularGlossinessMaterial, BaseTexture } from "babylonjs";
+import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
+import { LineContainerComponent } from "../../../lineContainerComponent";
+import { Color3LineComponent } from "../../../lines/color3LineComponent";
+import { SliderLineComponent } from "../../../lines/sliderLineComponent";
+import { CommonMaterialPropertyGridComponent } from "./commonMaterialPropertyGridComponent";
+import { TextureLinkLineComponent } from "../../../lines/textureLinkLineComponent";
+import { LockObject } from "../lockObject";
+
+interface IPBRSpecularGlossinessMaterialPropertyGridComponentProps {
+    material: PBRSpecularGlossinessMaterial,
+    lockObject: LockObject,
+    onSelectionChangedObservable?: Observable<any>,
+    onPropertyChangedObservable?: Observable<PropertyChangedEvent>
+}
+
+export class PBRSpecularGlossinessMaterialPropertyGridComponent extends React.Component<IPBRSpecularGlossinessMaterialPropertyGridComponentProps> {
+    constructor(props: IPBRSpecularGlossinessMaterialPropertyGridComponentProps) {
+        super(props);
+    }
+
+    renderTextures() {
+        const material = this.props.material;
+
+        if (material.getActiveTextures().length === 0) {
+            return null;
+        }
+
+        const onDebugSelectionChangeObservable = new BABYLON.Observable<BaseTexture>();
+
+        return (
+            <LineContainerComponent title="TEXTURES">
+                <TextureLinkLineComponent label="Diffuse" texture={material.diffuseTexture} material={material} onSelectionChangedObservable={this.props.onSelectionChangedObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
+                <TextureLinkLineComponent label="Specular glossiness" texture={material.specularGlossinessTexture} material={material} onSelectionChangedObservable={this.props.onSelectionChangedObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
+                <TextureLinkLineComponent label="Environment" texture={material.environmentTexture} material={material} onSelectionChangedObservable={this.props.onSelectionChangedObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
+                <TextureLinkLineComponent label="Emissive" texture={material.emissiveTexture} material={material} onSelectionChangedObservable={this.props.onSelectionChangedObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
+                <TextureLinkLineComponent label="Lightmap" texture={material.lightmapTexture} material={material} onSelectionChangedObservable={this.props.onSelectionChangedObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
+            </LineContainerComponent>
+        )
+    }
+
+    render() {
+        const material = this.props.material;
+
+        return (
+            <div className="pane">
+                <CommonMaterialPropertyGridComponent lockObject={this.props.lockObject} material={material} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                {this.renderTextures()}
+                <LineContainerComponent title="LIGHTING & COLORS">
+                    <Color3LineComponent label="Diffuse" target={material} propertyName="diffuseColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <Color3LineComponent label="Specular" target={material} propertyName="specularColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                </LineContainerComponent>
+                <LineContainerComponent title="LEVELS" closed={true}>
+                    <SliderLineComponent label="Glossiness" target={material} propertyName="glossiness" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                </LineContainerComponent>
+            </div>
+        );
+    }
+}

+ 31 - 2
inspector/src/components/actionTabs/tabs/propertyGrids/materials/texturePropertyGridComponent.tsx

@@ -1,5 +1,5 @@
 import * as React from "react";
-import { Texture, BaseTexture, CubeTexture, Observable } from "babylonjs";
+import { Texture, BaseTexture, CubeTexture, Observable, Nullable } from "babylonjs";
 import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
 import { LineContainerComponent } from "../../../lineContainerComponent";
 import { SliderLineComponent } from "../../../lines/sliderLineComponent";
@@ -10,18 +10,45 @@ import { FloatLineComponent } from "../../../lines/floatLineComponent";
 import { OptionsLineComponent } from "../../../lines/optionsLineComponent";
 import { FileButtonLineComponent } from "../../../lines/fileButtonLineComponent";
 import { LockObject } from "../lockObject";
+import { ValueLineComponent } from "../../../lines/valueLineComponent";
+import { GlobalState } from "components/globalState";
 
 interface ITexturePropertyGridComponentProps {
     texture: BaseTexture,
     lockObject: LockObject,
+    globalState: GlobalState,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>
 }
 
 export class TexturePropertyGridComponent extends React.Component<ITexturePropertyGridComponentProps> {
+
+    private _adtInstrumentation: Nullable<BABYLON.GUI.AdvancedDynamicTextureInstrumentation>;
+
     constructor(props: ITexturePropertyGridComponentProps) {
         super(props);
     }
 
+    componentWillMount() {
+        const texture = this.props.texture
+
+        if (!texture || !(texture as any).rootContainer) {
+            return;
+        }
+
+        const adt = texture as BABYLON.GUI.AdvancedDynamicTexture;
+
+        this._adtInstrumentation = new BABYLON.GUI.AdvancedDynamicTextureInstrumentation(adt);
+        this._adtInstrumentation.captureRenderTime = true;
+        this._adtInstrumentation.captureLayoutTime = true;
+    }
+
+    componentWillUnmount() {
+        if (this._adtInstrumentation) {
+            this._adtInstrumentation.dispose();
+            this._adtInstrumentation = null;
+        }
+    }
+
     updateTexture(file: File) {
         const texture = this.props.texture;
         BABYLON.Tools.ReadFile(file, (data) => {
@@ -56,7 +83,7 @@ export class TexturePropertyGridComponent extends React.Component<ITextureProper
         return (
             <div className="pane">
                 <LineContainerComponent title="PREVIEW">
-                    <TextureLineComponent texture={texture} width={256} height={256} />
+                    <TextureLineComponent texture={texture} width={256} height={256} globalState={this.props.globalState} />
                     <FileButtonLineComponent label="Replace texture" onClick={(file) => this.updateTexture(file)} accept=".jpg, .png, .tga, .dds, .env" />
                 </LineContainerComponent>
                 <LineContainerComponent title="GENERAL">
@@ -76,6 +103,8 @@ export class TexturePropertyGridComponent extends React.Component<ITextureProper
                 {
                     (texture as any).rootContainer &&
                     <LineContainerComponent title="ADVANCED TEXTURE PROPERTIES">
+                        <ValueLineComponent label="Last layout time" value={this._adtInstrumentation!.renderTimeCounter.current} units="ms" />
+                        <ValueLineComponent label="Last render time" value={this._adtInstrumentation!.layoutTimeCounter.current} units="ms" />
                         <SliderLineComponent label="Render scale" minimum={0.1} maximum={5} step={0.1} target={texture} propertyName="renderScale" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         <CheckBoxLineComponent label="Premultiply alpha" target={texture} propertyName="premulAlpha" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         <FloatLineComponent lockObject={this.props.lockObject} label="Ideal width" target={texture} propertyName="idealWidth" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />

+ 2 - 0
inspector/src/components/globalState.ts

@@ -16,6 +16,8 @@ export class GlobalState {
     public glTFLoaderExtensionDefaults: { [name: string]: { [key: string]: any } } = {};
     public glTFLoaderDefaults: { [key: string]: any } = { "validate": true };
 
+    public blockMutationUpdates = false;
+
     public prepareGLTFPlugin(loader: GLTFFileLoader) {
         var loaderState = this.glTFLoaderDefaults;
         if (loaderState !== undefined) {

+ 4 - 0
inspector/src/components/sceneExplorer/sceneExplorerComponent.tsx

@@ -58,6 +58,10 @@ export class SceneExplorerComponent extends React.Component<ISceneExplorerCompon
     }
 
     processMutation() {
+        if (this.props.globalState.blockMutationUpdates) {
+            return;
+        }
+
         this.forceUpdate();
     }
 

+ 2 - 2
inspector/src/tools.ts

@@ -20,11 +20,11 @@ export class Tools {
         let result: Array<any> = [];
         for (let i of items) {
             // If the mesh is hidden, add it's children that are not hidden, this will handle the case of bounding box parenting for bounding box gizmo
-            if (i.reservedDataStore && i.reservedDataStore.hidden) {
+            if (i.reservedDataStore && i.reservedDataStore.hidden && i.getChildMeshes) {
                 Tools._RecursiveRemoveHiddenMeshesAndHoistChildren(i.getChildMeshes()).forEach((m) => {
                     result.push(m);
                 });
-            }else {
+            } else {
                 result.push(i);
             }
         }

+ 111 - 15
materialsLibrary/src/sky/babylon.skyMaterial.ts

@@ -1,6 +1,7 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON {
+    /** @hidden */
     class SkyMaterialDefines extends MaterialDefines {
         public CLIPPLANE = false;
         public CLIPPLANE2 = false;
@@ -17,60 +18,119 @@ module BABYLON {
         }
     }
 
+    /**
+     * This is the sky material which allows to create dynamic and texture free effects for skyboxes.
+     * @see https://doc.babylonjs.com/extensions/sky
+     */
     export class SkyMaterial extends PushMaterial {
-        // Public members
+        /**
+         * Defines the overall luminance of sky in interval ]0, 1[.
+         */
         @serialize()
         public luminance: number = 1.0;
-
+        /**
+         * Defines the amount (scattering) of haze as opposed to molecules in atmosphere.
+         */
         @serialize()
         public turbidity: number = 10.0;
-
+        /**
+         * Defines the sky appearance (light intensity).
+         */
         @serialize()
         public rayleigh: number = 2.0;
-
+        /**
+         * Defines the mieCoefficient in interval [0, 0.1] which affects the property .mieDirectionalG.
+         */
         @serialize()
         public mieCoefficient: number = 0.005;
-
+        /**
+         * Defines the amount of haze particles following the Mie scattering theory.
+         */
         @serialize()
         public mieDirectionalG: number = 0.8;
-
+        /**
+         * Defines the distance of the sun according to the active scene camera.
+         */
         @serialize()
         public distance: number = 500;
-
+        /**
+         * Defines the sun inclination, in interval [-0.5, 0.5]. When the inclination is not 0, the sun is said
+         * "inclined".
+         */
         @serialize()
         public inclination: number = 0.49;
-
+        /**
+         * Defines the solar azimuth in interval [0, 1]. The azimuth is the angle in the horizontal plan between
+         * an object direction and a reference direction.
+         */
         @serialize()
         public azimuth: number = 0.25;
-
+        /**
+         * Defines the sun position in the sky on (x,y,z). If the property .useSunPosition is set to false, then
+         * the property is overriden by the inclination and the azimuth and can be read at any moment.
+         */
         @serializeAsVector3()
         public sunPosition: Vector3 = new Vector3(0, 100, 0);
-
+        /**
+         * Defines if the sun position should be computed (inclination and azimuth) according to the given
+         * .sunPosition property.
+         */
         @serialize()
         public useSunPosition: boolean = false;
+        /**
+         * Defines an offset vector used to get a horizon offset.
+         * @example skyMaterial.cameraOffset.y = camera.globalPosition.y // Set horizon relative to 0 on the Y axis
+         */
+        @serialize()
+        public cameraOffset: Vector3 = Vector3.Zero();
 
-        // Private members
         private _cameraPosition: Vector3 = Vector3.Zero();
-
         private _renderId: number;
 
+        /**
+         * Instantiates a new sky material.
+         * This material allows to create dynamic and texture free
+         * effects for skyboxes by taking care of the atmosphere state.
+         * @see https://doc.babylonjs.com/extensions/sky
+         * @param name Define the name of the material in the scene
+         * @param scene Define the scene the material belong to
+         */
         constructor(name: string, scene: Scene) {
             super(name, scene);
         }
 
+        /**
+         * Specifies if the material will require alpha blending
+         * @returns a boolean specifying if alpha blending is needed
+         */
         public needAlphaBlending(): boolean {
             return (this.alpha < 1.0);
         }
 
+        /**
+         * Specifies if this material should be rendered in alpha test mode
+         * @returns false as the sky material doesn't need alpha testing.
+         */
         public needAlphaTesting(): boolean {
             return false;
         }
 
+        /**
+         * Get the texture used for alpha test purpose.
+         * @returns null as the sky material has no texture.
+         */
         public getAlphaTestTexture(): Nullable<BaseTexture> {
             return null;
         }
 
-        // Methods
+        /**
+         * Get if the submesh is ready to be used and all its information available.
+         * Child classes can use it to update shaders
+         * @param mesh defines the mesh to check
+         * @param subMesh defines which submesh to check
+         * @param useInstances specifies that instances should be used
+         * @returns a boolean indicating that the submesh is ready or not
+         */
         public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
             if (this.isFrozen) {
                 if (this._wasPreviouslyReady && subMesh.effect) {
@@ -123,7 +183,7 @@ module BABYLON {
                     ["world", "viewProjection", "view",
                         "vFogInfos", "vFogColor", "pointSize", "vClipPlane", "vClipPlane2", "vClipPlane3", "vClipPlane4",
                         "luminance", "turbidity", "rayleigh", "mieCoefficient", "mieDirectionalG", "sunPosition",
-                        "cameraPosition"
+                        "cameraPosition", "cameraOffset"
                     ],
                     [],
                     join, fallbacks, this.onCompiled, this.onError), defines);
@@ -139,6 +199,12 @@ module BABYLON {
             return true;
         }
 
+        /**
+         * Binds the submesh to this material by preparing the effect and shader to draw
+         * @param world defines the world transformation matrix
+         * @param mesh defines the mesh containing the submesh
+         * @param subMesh defines the submesh to bind the material to
+         */
         public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
             var scene = this.getScene();
 
@@ -185,6 +251,8 @@ module BABYLON {
                 this._activeEffect.setVector3("cameraPosition", this._cameraPosition);
             }
 
+            this._activeEffect.setVector3("cameraOffset", this.cameraOffset);
+
             if (this.luminance > 0) {
                 this._activeEffect.setFloat("luminance", this.luminance);
             }
@@ -208,29 +276,57 @@ module BABYLON {
             this._afterBind(mesh, this._activeEffect);
         }
 
+        /**
+         * Get the list of animatables in the material.
+         * @returns the list of animatables object used in the material
+         */
         public getAnimatables(): IAnimatable[] {
             return [];
         }
 
+        /**
+         * Disposes the material
+         * @param forceDisposeEffect specifies if effects should be forcefully disposed
+         */
         public dispose(forceDisposeEffect?: boolean): void {
             super.dispose(forceDisposeEffect);
         }
 
+        /**
+         * Makes a duplicate of the material, and gives it a new name
+         * @param name defines the new name for the duplicated material
+         * @returns the cloned material
+         */
         public clone(name: string): SkyMaterial {
             return SerializationHelper.Clone<SkyMaterial>(() => new SkyMaterial(name, this.getScene()), this);
         }
 
+        /**
+         * Serializes this material in a JSON representation
+         * @returns the serialized material object
+         */
         public serialize(): any {
             var serializationObject = SerializationHelper.Serialize(this);
             serializationObject.customType  = "BABYLON.SkyMaterial";
             return serializationObject;
         }
 
+        /**
+         * Gets the current class name of the material e.g. "SkyMaterial"
+         * Mainly use in serialization.
+         * @returns the class name
+         */
         public getClassName(): string {
             return "SkyMaterial";
         }
 
-        // Statics
+        /**
+         * Creates a sky material from parsed material data
+         * @param source defines the JSON representation of the material
+         * @param scene defines the hosting scene
+         * @param rootUrl defines the root URL to use to load textures and relative dependencies
+         * @returns a new sky material
+         */
         public static Parse(source: any, scene: Scene, rootUrl: string): SkyMaterial {
             return SerializationHelper.Parse(() => new SkyMaterial(source.name, scene), source, scene, rootUrl);
         }

+ 3 - 2
materialsLibrary/src/sky/sky.fragment.fx

@@ -11,6 +11,7 @@ varying vec4 vColor;
 
 // Sky
 uniform vec3 cameraPosition;
+uniform vec3 cameraOffset;
 uniform float luminance;
 uniform float turbidity;
 uniform float rayleigh;
@@ -102,7 +103,7 @@ void main(void) {
 	float sunE = sunIntensity(dot(sunDirection, up));
 	vec3 betaR = simplifiedRayleigh() * rayleighCoefficient;
 	vec3 betaM = totalMie(lambda, K, turbidity) * mieCoefficient;
-	float zenithAngle = acos(max(0.0, dot(up, normalize(vPositionW - cameraPosition))));
+	float zenithAngle = acos(max(0.0, dot(up, normalize(vPositionW - cameraPosition + cameraOffset))));
 	float sR = rayleighZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));
 	float sM = mieZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));
 	vec3 Fex = exp(-(betaR * sR + betaM * sM));
@@ -125,7 +126,7 @@ void main(void) {
 	L0 += (sunE * 19000.0 * Fex) * sundisk;
 	
 	vec3 whiteScale = 1.0/Uncharted2Tonemap(vec3(W));
-	vec3 texColor = (Lin+L0);   
+	vec3 texColor = (Lin+L0);
 	texColor *= 0.04 ;
 	texColor += vec3(0.0,0.001,0.0025)*0.3;
 

+ 1 - 1
package.json

@@ -9,7 +9,7 @@
     ],
     "name": "babylonjs",
     "description": "Babylon.js is a JavaScript 3D engine based on webgl.",
-    "version": "4.0.0-alpha.11",
+    "version": "4.0.0-alpha.14",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 34 - 33
src/Cameras/Inputs/babylon.arcRotateCameraKeyboardMoveInput.ts

@@ -94,44 +94,45 @@ module BABYLON {
 
             this._onKeyboardObserver = this._scene.onKeyboardObservable.add((info) => {
                 let evt = info.event;
+                if (!evt.metaKey) {
+                    if (info.type === KeyboardEventTypes.KEYDOWN) {
+                        this._ctrlPressed = evt.ctrlKey;
+                        this._altPressed = evt.altKey;
+
+                        if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
+                            this.keysDown.indexOf(evt.keyCode) !== -1 ||
+                            this.keysLeft.indexOf(evt.keyCode) !== -1 ||
+                            this.keysRight.indexOf(evt.keyCode) !== -1 ||
+                            this.keysReset.indexOf(evt.keyCode) !== -1) {
+                            var index = this._keys.indexOf(evt.keyCode);
+
+                            if (index === -1) {
+                                this._keys.push(evt.keyCode);
+                            }
 
-                if (info.type === KeyboardEventTypes.KEYDOWN) {
-                    this._ctrlPressed = evt.ctrlKey;
-                    this._altPressed = evt.altKey;
-
-                    if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
-                        this.keysDown.indexOf(evt.keyCode) !== -1 ||
-                        this.keysLeft.indexOf(evt.keyCode) !== -1 ||
-                        this.keysRight.indexOf(evt.keyCode) !== -1 ||
-                        this.keysReset.indexOf(evt.keyCode) !== -1) {
-                        var index = this._keys.indexOf(evt.keyCode);
-
-                        if (index === -1) {
-                            this._keys.push(evt.keyCode);
-                        }
-
-                        if (evt.preventDefault) {
-                            if (!noPreventDefault) {
-                                evt.preventDefault();
+                            if (evt.preventDefault) {
+                                if (!noPreventDefault) {
+                                    evt.preventDefault();
+                                }
                             }
                         }
                     }
-                }
-                else {
-                    if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
-                        this.keysDown.indexOf(evt.keyCode) !== -1 ||
-                        this.keysLeft.indexOf(evt.keyCode) !== -1 ||
-                        this.keysRight.indexOf(evt.keyCode) !== -1 ||
-                        this.keysReset.indexOf(evt.keyCode) !== -1) {
-                        var index = this._keys.indexOf(evt.keyCode);
-
-                        if (index >= 0) {
-                            this._keys.splice(index, 1);
-                        }
+                    else {
+                        if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
+                            this.keysDown.indexOf(evt.keyCode) !== -1 ||
+                            this.keysLeft.indexOf(evt.keyCode) !== -1 ||
+                            this.keysRight.indexOf(evt.keyCode) !== -1 ||
+                            this.keysReset.indexOf(evt.keyCode) !== -1) {
+                            var index = this._keys.indexOf(evt.keyCode);
+
+                            if (index >= 0) {
+                                this._keys.splice(index, 1);
+                            }
 
-                        if (evt.preventDefault) {
-                            if (!noPreventDefault) {
-                                evt.preventDefault();
+                            if (evt.preventDefault) {
+                                if (!noPreventDefault) {
+                                    evt.preventDefault();
+                                }
                             }
                         }
                     }

+ 27 - 26
src/Cameras/Inputs/babylon.freeCameraKeyboardMoveInput.ts

@@ -58,33 +58,34 @@ module BABYLON {
 
             this._onKeyboardObserver = this._scene.onKeyboardObservable.add((info) => {
                 let evt = info.event;
-
-                if (info.type === KeyboardEventTypes.KEYDOWN) {
-                    if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
-                        this.keysDown.indexOf(evt.keyCode) !== -1 ||
-                        this.keysLeft.indexOf(evt.keyCode) !== -1 ||
-                        this.keysRight.indexOf(evt.keyCode) !== -1) {
-                        var index = this._keys.indexOf(evt.keyCode);
-
-                        if (index === -1) {
-                            this._keys.push(evt.keyCode);
-                        }
-                        if (!noPreventDefault) {
-                            evt.preventDefault();
-                        }
-                    }
-                } else {
-                    if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
-                        this.keysDown.indexOf(evt.keyCode) !== -1 ||
-                        this.keysLeft.indexOf(evt.keyCode) !== -1 ||
-                        this.keysRight.indexOf(evt.keyCode) !== -1) {
-                        var index = this._keys.indexOf(evt.keyCode);
-
-                        if (index >= 0) {
-                            this._keys.splice(index, 1);
+                if (!evt.metaKey) {
+                    if (info.type === KeyboardEventTypes.KEYDOWN) {
+                        if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
+                            this.keysDown.indexOf(evt.keyCode) !== -1 ||
+                            this.keysLeft.indexOf(evt.keyCode) !== -1 ||
+                            this.keysRight.indexOf(evt.keyCode) !== -1) {
+                            var index = this._keys.indexOf(evt.keyCode);
+
+                            if (index === -1) {
+                                this._keys.push(evt.keyCode);
+                            }
+                            if (!noPreventDefault) {
+                                evt.preventDefault();
+                            }
                         }
-                        if (!noPreventDefault) {
-                            evt.preventDefault();
+                    } else {
+                        if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
+                            this.keysDown.indexOf(evt.keyCode) !== -1 ||
+                            this.keysLeft.indexOf(evt.keyCode) !== -1 ||
+                            this.keysRight.indexOf(evt.keyCode) !== -1) {
+                            var index = this._keys.indexOf(evt.keyCode);
+
+                            if (index >= 0) {
+                                this._keys.splice(index, 1);
+                            }
+                            if (!noPreventDefault) {
+                                evt.preventDefault();
+                            }
                         }
                     }
                 }

+ 11 - 2
src/Culling/babylon.boundingInfo.ts

@@ -148,17 +148,26 @@ module BABYLON {
         /**
          * Returns `true` if the bounding info is within the frustum defined by the passed array of planes.
          * @param frustumPlanes defines the frustum to test
-         * @param strategy defines the strategy to use for the culling (default is BABYLON.Scene.CULLINGSTRATEGY_STANDARD)
+         * @param strategy defines the strategy to use for the culling (default is BABYLON.AbstractMesh.CULLINGSTRATEGY_STANDARD)
          * @returns true if the bounding info is in the frustum planes
          */
         public isInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>, strategy: number = AbstractMesh.CULLINGSTRATEGY_STANDARD): boolean {
+            let inclusionTest = (strategy === AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION || strategy === AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY);
+            if (inclusionTest) {
+                if (this.boundingSphere.isCenterInFrustum(frustumPlanes)) {
+                    return true;
+                }
+            }
+
             if (!this.boundingSphere.isInFrustum(frustumPlanes)) {
                 return false;
             }
 
-            if (strategy === AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY) {
+            let bSphereOnlyTest = (strategy === AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY || strategy === AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY);
+            if (bSphereOnlyTest) {
                 return true;
             }
+
             return this.boundingBox.isInFrustum(frustumPlanes);
         }
 

+ 19 - 2
src/Culling/babylon.boundingSphere.ts

@@ -105,12 +105,29 @@ module BABYLON {
          * @returns true if there is an intersection
          */
         public isInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
-            for (var i = 0; i < 6; i++) {
-                if (frustumPlanes[i].dotCoordinate(this.centerWorld) <= -this.radiusWorld) {
+            let center = this.centerWorld;
+            let radius = this.radiusWorld;
+            for (let i = 0; i < 6; i++) {
+                if (frustumPlanes[i].dotCoordinate(center) <= -radius) {
                     return false;
                 }
             }
+            return true;
+        }
 
+        /**
+         * Tests if the bounding sphere center is in between the frustum planes.
+         * Used for optimistic fast inclusion.
+         * @param frustumPlanes defines the frustum planes to test
+         * @returns true if the sphere center is in between the frustum planes
+         */
+        public isCenterInFrustum(frustumPlanes: Array<DeepImmutable<Plane>>): boolean {
+            let center = this.centerWorld;
+            for (let i = 0; i < 6; i++) {
+                if (frustumPlanes[i].dotCoordinate(center) < 0) {
+                    return false;
+                }
+            }
             return true;
         }
 

+ 17 - 2
src/Debug/babylon.debugLayer.ts

@@ -114,7 +114,7 @@ module BABYLON {
 
         private _scene: Scene;
 
-        private BJSINSPECTOR = typeof INSPECTOR !== 'undefined' ? INSPECTOR : undefined;
+        private BJSINSPECTOR = this._getGlobalInspector();
 
         /**
          * Observable triggered when a property is changed through the inspector.
@@ -154,11 +154,26 @@ module BABYLON {
                 ...config
             };
 
-            this.BJSINSPECTOR = this.BJSINSPECTOR || typeof INSPECTOR !== 'undefined' ? INSPECTOR : undefined;
+            this.BJSINSPECTOR = this.BJSINSPECTOR || this._getGlobalInspector();
 
             this.BJSINSPECTOR.Inspector.Show(this._scene, userOptions);
         }
 
+        /** Get the inspector from bundle or global */
+        private _getGlobalInspector(): any {
+            // UMD Global name detection from Webpack Bundle UMD Name.
+            if (typeof INSPECTOR !== 'undefined') {
+                return INSPECTOR;
+            }
+
+            // In case of module let s check the global emitted from the Inspector entry point.
+            if (BABYLON && (BABYLON as any).Inspector) {
+                return BABYLON;
+            }
+
+            return undefined;
+        }
+
         /**
          * Get if the inspector is visible or not.
          * @returns true if visible otherwise, false

+ 3 - 5
src/Engine/babylon.engine.ts

@@ -481,7 +481,7 @@ module BABYLON {
          * Returns the current version of the framework
          */
         public static get Version(): string {
-            return "4.0.0-alpha.11";
+            return "4.0.0-alpha.14";
         }
 
         /**
@@ -4312,8 +4312,7 @@ module BABYLON {
                         customFallback = true;
                         excludeLoaders.push(loader);
                         Tools.Warn((loader.constructor as any).name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
-                        this.createTexture(urlArg, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture, undefined, undefined, excludeLoaders);
-                        return;
+                        this.createTexture(urlArg, noMipmap, texture.invertY, scene, samplingMode, null, null, buffer, texture, undefined, undefined, excludeLoaders);
                     }
                 }
 
@@ -4322,8 +4321,7 @@ module BABYLON {
                         texture.onLoadedObservable.remove(onLoadObserver);
                     }
                     if (Tools.UseFallbackTexture) {
-                        this.createTexture(Tools.fallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture);
-                        return;
+                        this.createTexture(Tools.fallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, null, buffer, texture);
                     }
                 }
 

+ 30 - 6
src/Materials/Textures/babylon.baseTexture.ts

@@ -147,13 +147,41 @@ module BABYLON {
          * Define if the texture is a cube texture or if false a 2d texture.
          */
         @serialize()
-        public isCube = false;
+        public get isCube(): boolean {
+            if (!this._texture) {
+                return false;
+            }
+
+            return this._texture.isCube;
+        }
+
+        public set isCube(value: boolean) {
+            if (!this._texture) {
+                return;
+            }
+
+            this._texture.isCube = value;
+        }
 
         /**
          * Define if the texture is a 3d texture (webgl 2) or if false a 2d texture.
          */
         @serialize()
-        public is3D = false;
+        public get is3D(): boolean {
+            if (!this._texture) {
+                return false;
+            }
+
+            return this._texture.is3D;
+        }
+
+        public set is3D(value: boolean) {
+            if (!this._texture) {
+                return;
+            }
+
+            this._texture.is3D = value;
+        }
 
         /**
          * Define if the texture contains data in gamma space (most of the png/jpg aside bump).
@@ -277,9 +305,6 @@ module BABYLON {
         private _scene: Nullable<Scene>;
 
         /** @hidden */
-        public _samplingMode: number;
-
-        /** @hidden */
         public _texture: Nullable<InternalTexture>;
         private _uid: Nullable<string>;
 
@@ -439,7 +464,6 @@ module BABYLON {
                 return;
             }
 
-            this._samplingMode = samplingMode;
             scene.getEngine().updateTextureSamplingMode(samplingMode, this._texture);
         }
 

+ 1 - 1
src/Materials/Textures/babylon.dynamicTexture.ts

@@ -70,7 +70,7 @@ module BABYLON {
 
             this.releaseInternalTexture();
 
-            this._texture = this._engine.createDynamicTexture(textureSize.width, textureSize.height, this._generateMipMaps, this._samplingMode);
+            this._texture = this._engine.createDynamicTexture(textureSize.width, textureSize.height, this._generateMipMaps, this.samplingMode);
         }
 
         /**

+ 14 - 7
src/Materials/Textures/babylon.texture.ts

@@ -172,6 +172,9 @@ module BABYLON {
         private _cachedCoordinatesMode: number;
 
         /** @hidden */
+        protected _initialSamplingMode = Texture.BILINEAR_SAMPLINGMODE;
+
+        /** @hidden */
         public _buffer: Nullable<string | ArrayBuffer | HTMLImageElement | Blob>;
         private _deleteBuffer: boolean;
         protected _format: Nullable<number>;
@@ -200,7 +203,11 @@ module BABYLON {
          * Get the current sampling mode associated with the texture.
          */
         public get samplingMode(): number {
-            return this._samplingMode;
+            if (!this._texture) {
+                return this._initialSamplingMode;
+            }
+
+            return this._texture.samplingMode;
         }
 
         /**
@@ -232,7 +239,7 @@ module BABYLON {
             this.url = url;
             this._noMipmap = noMipmap;
             this._invertY = invertY;
-            this._samplingMode = samplingMode;
+            this._initialSamplingMode = samplingMode;
             this._buffer = buffer;
             this._deleteBuffer = deleteBuffer;
             if (format) {
@@ -272,7 +279,7 @@ module BABYLON {
 
             if (!this._texture) {
                 if (!scene.useDelayedTextureLoading) {
-                    this._texture = scene.getEngine().createTexture(this.url, noMipmap, invertY, scene, this._samplingMode, load, onError, this._buffer, undefined, this._format);
+                    this._texture = scene.getEngine().createTexture(this.url, noMipmap, invertY, scene, samplingMode, load, onError, this._buffer, undefined, this._format);
                     if (deleteBuffer) {
                         delete this._buffer;
                     }
@@ -329,10 +336,10 @@ module BABYLON {
             }
 
             this.delayLoadState = Engine.DELAYLOADSTATE_LOADED;
-            this._texture = this._getFromCache(this.url, this._noMipmap, this._samplingMode);
+            this._texture = this._getFromCache(this.url, this._noMipmap, this.samplingMode);
 
             if (!this._texture) {
-                this._texture = scene.getEngine().createTexture(this.url, this._noMipmap, this._invertY, scene, this._samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer, null, this._format);
+                this._texture = scene.getEngine().createTexture(this.url, this._noMipmap, this._invertY, scene, this.samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer, null, this._format);
                 if (this._deleteBuffer) {
                     delete this._buffer;
                 }
@@ -506,7 +513,7 @@ module BABYLON {
          */
         public clone(): Texture {
             return SerializationHelper.Clone(() => {
-                return new Texture(this._texture ? this._texture.url : null, this.getScene(), this._noMipmap, this._invertY, this._samplingMode);
+                return new Texture(this._texture ? this._texture.url : null, this.getScene(), this._noMipmap, this._invertY, this.samplingMode);
             }, this);
         }
 
@@ -625,7 +632,7 @@ module BABYLON {
             // Update Sampling Mode
             if (parsedTexture.samplingMode) {
                 var sampling: number = parsedTexture.samplingMode;
-                if (texture && texture._samplingMode !== sampling) {
+                if (texture && texture.samplingMode !== sampling) {
                     texture.updateSamplingMode(sampling);
                 }
             }

+ 2 - 2
src/Materials/Textures/babylon.videoTexture.ts

@@ -90,7 +90,7 @@ module BABYLON {
 
             this._engine = this.getScene()!.getEngine();
             this._generateMipMaps = generateMipMaps;
-            this._samplingMode = samplingMode;
+            this._initialSamplingMode = samplingMode;
             this.autoUpdateTexture = settings.autoUpdateTexture;
 
             this.name = name || this._getName(src);
@@ -184,7 +184,7 @@ module BABYLON {
                 this.video.videoWidth,
                 this.video.videoHeight,
                 this._generateMipMaps,
-                this._samplingMode
+                this.samplingMode
             );
 
             if (!this.video.autoplay && !this._settings.poster) {

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

@@ -1674,10 +1674,10 @@ module BABYLON {
 
         /**
          * Creates a standard material from parsed material data
-         * @param source defines the JSON represnetation of the material
+         * @param source defines the JSON representation of the material
          * @param scene defines the hosting scene
          * @param rootUrl defines the root URL to use to load textures and relative dependencies
-         * @returns a new material
+         * @returns a new standard material
          */
         public static Parse(source: any, scene: Scene, rootUrl: string): StandardMaterial {
             return SerializationHelper.Parse(() => new StandardMaterial(source.name, scene), source, scene, rootUrl);

+ 42 - 3
src/Mesh/babylon.abstractMesh.ts

@@ -44,10 +44,40 @@ module BABYLON {
         /** Use a conservative occlusion algorithm */
         public static OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE = 1;
 
-        /** Default culling strategy with bounding box and bounding sphere and then frustum culling */
+        /** Default culling strategy : this is an exclusion test and it's the more accurate.
+         *  Test order :
+         *  Is the bounding sphere outside the frustum ?
+         *  If not, are the bounding box vertices outside the frustum ?
+         *  It not, then the cullable object is in the frustum.
+         */
         public static readonly CULLINGSTRATEGY_STANDARD = 0;
-        /** Culling strategy with bounding sphere only and then frustum culling */
+        /** Culling strategy : Bounding Sphere Only.
+         *  This is an exclusion test. It's faster than the standard strategy because the bounding box is not tested.
+         *  It's also less accurate than the standard because some not visible objects can still be selected.
+         *  Test : is the bounding sphere outside the frustum ?
+         *  If not, then the cullable object is in the frustum.
+         */
         public static readonly CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY = 1;
+        /** Culling strategy : Optimistic Inclusion.
+         *  This in an inclusion test first, then the standard exclusion test.
+         *  This can be faster when a cullable object is expected to be almost always in the camera frustum.
+         *  This could also be a little slower than the standard test when the tested object center is not the frustum but one of its bounding box vertex is still inside.
+         *  Anyway, it's as accurate as the standard strategy.
+         *  Test :
+         *  Is the cullable object bounding sphere center in the frustum ?
+         *  If not, apply the default culling strategy.
+         */
+        public static readonly CULLINGSTRATEGY_OPTIMISTIC_INCLUSION = 2;
+        /** Culling strategy : Optimistic Inclusion then Bounding Sphere Only.
+         *  This in an inclusion test first, then the bounding sphere only exclusion test.
+         *  This can be the fastest test when a cullable object is expected to be almost always in the camera frustum.
+         *  This could also be a little slower than the BoundingSphereOnly strategy when the tested object center is not in the frustum but its bounding sphere still intersects it.
+         *  It's less accurate than the standard strategy and as accurate as the BoundingSphereOnly strategy.
+         *  Test :
+         *  Is the cullable object bounding sphere center in the frustum ?
+         *  If not, apply the Bounding Sphere Only strategy. No Bounding Box is tested here.
+         */
+        public static readonly CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY = 3;
 
         /**
          * No billboard
@@ -78,7 +108,16 @@ module BABYLON {
 
         private _facetData = new _FacetDataStorage();
 
-        /** Gets ot sets the culling strategy to use to find visible meshes */
+        /**
+         * The culling strategy to use to check whether the mesh must be rendered or not.
+         * This value can be changed at any time and will be used on the next render mesh selection.
+         * The possible values are :
+         * - AbstractMesh.CULLINGSTRATEGY_STANDARD
+         * - AbstractMesh.CULLINGSTRATEGY_BOUNDINGSPHERE_ONLY
+         * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION
+         * - AbstractMesh.CULLINGSTRATEGY_OPTIMISTIC_INCLUSION_THEN_BSPHERE_ONLY
+         * Please read each static variable documentation to get details about the culling process.
+         * */
         public cullingStrategy = AbstractMesh.CULLINGSTRATEGY_STANDARD;
 
         /**

+ 23 - 15
src/Mesh/babylon.geometry.ts

@@ -516,7 +516,15 @@ module BABYLON {
             if (!this._indexBufferIsUpdatable) {
                 this.setIndices(indices, null, true);
             } else {
+                const needToUpdateSubMeshes = indices.length !== this._indices.length;
+
+                this._indices = indices;
                 this._engine.updateDynamicIndexBuffer(this._indexBuffer, indices, offset);
+                if (needToUpdateSubMeshes) {
+                    for (const mesh of this._meshes) {
+                        mesh._createGlobalSubMesh(true);
+                    }
+                }
             }
         }
 
@@ -543,12 +551,10 @@ module BABYLON {
                 this._totalVertices = totalVertices;
             }
 
-            var meshes = this._meshes;
-            var numOfMeshes = meshes.length;
-
-            for (var index = 0; index < numOfMeshes; index++) {
-                meshes[index]._createGlobalSubMesh(true);
+            for (const mesh of this._meshes) {
+                mesh._createGlobalSubMesh(true);
             }
+
             this.notifyUpdate();
         }
 
@@ -913,17 +919,19 @@ module BABYLON {
                 // using slice() to make a copy of the array and not just reference it
                 var data = this.getVerticesData(kind);
 
-                if (data instanceof Float32Array) {
-                    vertexData.set(new Float32Array(<Float32Array>data), kind);
-                } else {
-                    vertexData.set((<number[]>data).slice(0), kind);
-                }
-                if (!stopChecking) {
-                    let vb = this.getVertexBuffer(kind);
+                if (data) {
+                    if (data instanceof Float32Array) {
+                        vertexData.set(new Float32Array(<Float32Array>data), kind);
+                    } else {
+                        vertexData.set((<number[]>data).slice(0), kind);
+                    }
+                    if (!stopChecking) {
+                        let vb = this.getVertexBuffer(kind);
 
-                    if (vb) {
-                        updatable = vb.isUpdatable();
-                        stopChecking = !updatable;
+                        if (vb) {
+                            updatable = vb.isUpdatable();
+                            stopChecking = !updatable;
+                        }
                     }
                 }
             }

+ 3 - 1
src/Mesh/babylon.mesh.ts

@@ -264,7 +264,9 @@ module BABYLON {
                 // Deep copy
                 Tools.DeepCopy(source, this, ["name", "material", "skeleton", "instances", "parent", "uniqueId",
                     "source", "metadata", "hasLODLevels", "geometry", "isBlocked", "areNormalsFrozen",
-                    "onBeforeDrawObservable", "onBeforeRenderObservable", "onAfterRenderObservable", "onBeforeDraw"
+                    "onBeforeDrawObservable", "onBeforeRenderObservable", "onAfterRenderObservable", "onBeforeDraw",
+                    "onAfterWorldMatrixUpdateObservable", "onCollideObservable", "onCollisionPositionChangeObservable", "onRebuildObservable",
+                    "onDisposeObservable"
                 ],
                     ["_poseMatrix"]);
 

+ 16 - 16
src/Mesh/babylon.meshBuilder.ts

@@ -4,7 +4,7 @@ module BABYLON {
      * Class containing static functions to help procedurally build meshes
      */
     export class MeshBuilder {
-        private static updateSideOrientation(orientation?: number): number {
+        private static _UpdateSideOrientation(orientation?: number): number {
             if (orientation == Mesh.DOUBLESIDE) {
                 return Mesh.DOUBLESIDE;
             }
@@ -34,7 +34,7 @@ module BABYLON {
         public static CreateBox(name: string, options: { size?: number, width?: number, height?: number, depth?: number, faceUV?: Vector4[], faceColors?: Color4[], sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4, updatable?: boolean }, scene: Nullable<Scene> = null): Mesh {
             var box = new Mesh(name, scene);
 
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             box._originalBuilderSideOrientation = options.sideOrientation;
 
             var vertexData = VertexData.CreateBox(options);
@@ -63,7 +63,7 @@ module BABYLON {
         public static CreateSphere(name: string, options: { segments?: number, diameter?: number, diameterX?: number, diameterY?: number, diameterZ?: number, arc?: number, slice?: number, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4, updatable?: boolean }, scene: any): Mesh {
             var sphere = new Mesh(name, scene);
 
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             sphere._originalBuilderSideOrientation = options.sideOrientation;
 
             var vertexData = VertexData.CreateSphere(options);
@@ -90,7 +90,7 @@ module BABYLON {
         public static CreateDisc(name: string, options: { radius?: number, tessellation?: number, arc?: number, updatable?: boolean, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }, scene: Nullable<Scene> = null): Mesh {
             var disc = new Mesh(name, scene);
 
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             disc._originalBuilderSideOrientation = options.sideOrientation;
 
             var vertexData = VertexData.CreateDisc(options);
@@ -118,7 +118,7 @@ module BABYLON {
         public static CreateIcoSphere(name: string, options: { radius?: number, radiusX?: number, radiusY?: number, radiusZ?: number, flat?: boolean, subdivisions?: number, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4, updatable?: boolean }, scene: Scene): Mesh {
             var sphere = new Mesh(name, scene);
 
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             sphere._originalBuilderSideOrientation = options.sideOrientation;
 
             var vertexData = VertexData.CreateIcoSphere(options);
@@ -155,7 +155,7 @@ module BABYLON {
             var pathArray = options.pathArray;
             var closeArray = options.closeArray;
             var closePath = options.closePath;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var instance = options.instance;
             var updatable = options.updatable;
 
@@ -302,7 +302,7 @@ module BABYLON {
         public static CreateCylinder(name: string, options: { height?: number, diameterTop?: number, diameterBottom?: number, diameter?: number, tessellation?: number, subdivisions?: number, arc?: number, faceColors?: Color4[], faceUV?: Vector4[], updatable?: boolean, hasRings?: boolean, enclose?: boolean, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }, scene: any): Mesh {
             var cylinder = new Mesh(name, scene);
 
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             cylinder._originalBuilderSideOrientation = options.sideOrientation;
 
             var vertexData = VertexData.CreateCylinder(options);
@@ -329,7 +329,7 @@ module BABYLON {
         public static CreateTorus(name: string, options: { diameter?: number, thickness?: number, tessellation?: number, updatable?: boolean, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }, scene: any): Mesh {
             var torus = new Mesh(name, scene);
 
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             torus._originalBuilderSideOrientation = options.sideOrientation;
 
             var vertexData = VertexData.CreateTorus(options);
@@ -357,7 +357,7 @@ module BABYLON {
         public static CreateTorusKnot(name: string, options: { radius?: number, tube?: number, radialSegments?: number, tubularSegments?: number, p?: number, q?: number, updatable?: boolean, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }, scene: any): Mesh {
             var torusKnot = new Mesh(name, scene);
 
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             torusKnot._originalBuilderSideOrientation = options.sideOrientation;
 
             var vertexData = VertexData.CreateTorusKnot(options);
@@ -560,7 +560,7 @@ module BABYLON {
             var rotation = options.rotation || 0;
             var cap = (options.cap === 0) ? 0 : options.cap || Mesh.NO_CAP;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var instance = options.instance || null;
             var invertUV = options.invertUV || false;
 
@@ -602,7 +602,7 @@ module BABYLON {
             var ribbonClosePath = options.ribbonClosePath || false;
             var cap = (options.cap === 0) ? 0 : options.cap || Mesh.NO_CAP;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var instance = options.instance;
             var invertUV = options.invertUV || false;
             return MeshBuilder._ExtrudeShapeGeneric(name, shape, path, null, null, scaleFunction, rotationFunction, ribbonCloseArray, ribbonClosePath, cap, true, scene, updatable ? true : false, sideOrientation, instance || null, invertUV, options.frontUVs || null, options.backUVs || null);
@@ -636,7 +636,7 @@ module BABYLON {
             var tessellation = options.tessellation || 64;
             var clip = options.clip || 0;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var cap = options.cap || Mesh.NO_CAP;
             var pi2 = Math.PI * 2;
             var paths = new Array();
@@ -686,7 +686,7 @@ module BABYLON {
         public static CreatePlane(name: string, options: { size?: number, width?: number, height?: number, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4, updatable?: boolean, sourcePlane?: Plane }, scene: Scene): Mesh {
             var plane = new Mesh(name, scene);
 
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             plane._originalBuilderSideOrientation = options.sideOrientation;
 
             var vertexData = VertexData.CreatePlane(options);
@@ -858,7 +858,7 @@ module BABYLON {
          * @returns the polygon mesh
          */
         public static CreatePolygon(name: string, options: { shape: Vector3[], holes?: Vector3[][], depth?: number, faceUV?: Vector4[], faceColors?: Color4[], updatable?: boolean, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }, scene: Scene): Mesh {
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             var shape = options.shape;
             var holes = options.holes || [];
             var depth = options.depth || 0;
@@ -940,7 +940,7 @@ module BABYLON {
             var cap = options.cap || Mesh.NO_CAP;
             var invertUV = options.invertUV || false;
             var updatable = options.updatable;
-            var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            var sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             options.arc = options.arc && (options.arc <= 0.0 || options.arc > 1.0) ? 1.0 : options.arc || 1.0;
 
             // tube geometry
@@ -1060,7 +1060,7 @@ module BABYLON {
         public static CreatePolyhedron(name: string, options: { type?: number, size?: number, sizeX?: number, sizeY?: number, sizeZ?: number, custom?: any, faceUV?: Vector4[], faceColors?: Color4[], flat?: boolean, updatable?: boolean, sideOrientation?: number, frontUVs?: Vector4, backUVs?: Vector4 }, scene: Scene): Mesh {
             var polyhedron = new Mesh(name, scene);
 
-            options.sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
+            options.sideOrientation = MeshBuilder._UpdateSideOrientation(options.sideOrientation);
             polyhedron._originalBuilderSideOrientation = options.sideOrientation;
 
             var vertexData = VertexData.CreatePolyhedron(options);

+ 18 - 33
src/Tools/babylon.khronosTextureContainer.ts

@@ -91,25 +91,24 @@ module BABYLON {
                 return;
             }
 
-            // load the reset of the header in native 32 bit int
-            var header = new Int32Array(this.arrayBuffer, 12, 13);
-
-            // determine of the remaining header values are recorded in the opposite endianness & require conversion
-            var oppositeEndianess = header[0] === 0x01020304;
-
-            // read all the header elements in order they exist in the file, without modification (sans endainness)
-            this.glType = oppositeEndianess ? this.switchEndianness(header[1]) : header[1]; // must be 0 for compressed textures
-            this.glTypeSize = oppositeEndianess ? this.switchEndianness(header[2]) : header[2]; // must be 1 for compressed textures
-            this.glFormat = oppositeEndianess ? this.switchEndianness(header[3]) : header[3]; // must be 0 for compressed textures
-            this.glInternalFormat = oppositeEndianess ? this.switchEndianness(header[4]) : header[4]; // the value of arg passed to gl.compressedTexImage2D(,,x,,,,)
-            this.glBaseInternalFormat = oppositeEndianess ? this.switchEndianness(header[5]) : header[5]; // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only)
-            this.pixelWidth = oppositeEndianess ? this.switchEndianness(header[6]) : header[6]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,)
-            this.pixelHeight = oppositeEndianess ? this.switchEndianness(header[7]) : header[7]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,)
-            this.pixelDepth = oppositeEndianess ? this.switchEndianness(header[8]) : header[8]; // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,)
-            this.numberOfArrayElements = oppositeEndianess ? this.switchEndianness(header[9]) : header[9]; // used for texture arrays
-            this.numberOfFaces = oppositeEndianess ? this.switchEndianness(header[10]) : header[10]; // used for cubemap textures, should either be 1 or 6
-            this.numberOfMipmapLevels = oppositeEndianess ? this.switchEndianness(header[11]) : header[11]; // number of levels; disregard possibility of 0 for compressed textures
-            this.bytesOfKeyValueData = oppositeEndianess ? this.switchEndianness(header[12]) : header[12]; // the amount of space after the header for meta-data
+            // load the reset of the header in native 32 bit uint
+            var dataSize = Uint32Array.BYTES_PER_ELEMENT;
+            var headerDataView = new DataView(this.arrayBuffer, 12, 13 * dataSize);
+            var endianness = headerDataView.getUint32(0, true);
+            var littleEndian = endianness === 0x04030201;
+
+            this.glType = headerDataView.getUint32(1 * dataSize, littleEndian); // must be 0 for compressed textures
+            this.glTypeSize = headerDataView.getUint32(2 * dataSize, littleEndian); // must be 1 for compressed textures
+            this.glFormat = headerDataView.getUint32(3 * dataSize, littleEndian); // must be 0 for compressed textures
+            this.glInternalFormat = headerDataView.getUint32(4 * dataSize, littleEndian); // the value of arg passed to gl.compressedTexImage2D(,,x,,,,)
+            this.glBaseInternalFormat = headerDataView.getUint32(5 * dataSize, littleEndian); // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only)
+            this.pixelWidth = headerDataView.getUint32(6 * dataSize, littleEndian); // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,)
+            this.pixelHeight = headerDataView.getUint32(7 * dataSize, littleEndian); // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,)
+            this.pixelDepth = headerDataView.getUint32(8 * dataSize, littleEndian); // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,)
+            this.numberOfArrayElements = headerDataView.getUint32(9 * dataSize, littleEndian); // used for texture arrays
+            this.numberOfFaces = headerDataView.getUint32(10 * dataSize, littleEndian); // used for cubemap textures, should either be 1 or 6
+            this.numberOfMipmapLevels = headerDataView.getUint32(11 * dataSize, littleEndian); // number of levels; disregard possibility of 0 for compressed textures
+            this.bytesOfKeyValueData = headerDataView.getUint32(12 * dataSize, littleEndian); // the amount of space after the header for meta-data
 
             // Make sure we have a compressed type.  Not only reduces work, but probably better to let dev know they are not compressing.
             if (this.glType !== 0) {
@@ -140,20 +139,6 @@ module BABYLON {
             this.loadType = KhronosTextureContainer.COMPRESSED_2D;
         }
 
-        //
-        /**
-         * Revert the endianness of a value.
-         * Not as fast hardware based, but will probably never need to use
-         * @param val defines the value to convert
-         * @returns the new value
-         */
-        public switchEndianness(val: number): number {
-            return ((val & 0xFF) << 24)
-                | ((val & 0xFF00) << 8)
-                | ((val >> 8) & 0xFF00)
-                | ((val >> 24) & 0xFF);
-        }
-
         /**
          * Uploads KTX content to a Babylon Texture.
          * It is assumed that the texture has already been created & is currently bound

+ 1 - 1
src/Tools/babylon.textureTools.ts

@@ -24,7 +24,7 @@ module BABYLON {
                 true,
                 (<InternalTexture>texture._texture).type,
                 false,
-                texture._samplingMode,
+                texture.samplingMode,
                 false
             );
 

+ 26 - 26
src/babylon.scene.ts

@@ -66,10 +66,10 @@ module BABYLON {
     /** Interface defining initialization parameters for Scene class */
     export interface SceneOptions {
         /**
-         * Defines that scene should keep up-to-date a map of geometry to enable fast look-up by Id
+         * Defines that scene should keep up-to-date a map of geometry to enable fast look-up by uniqueId
          * It will improve performance when the number of geometries becomes important.
          */
-        useGeometryIdsMap?: boolean;
+        useGeometryUniqueIdsMap?: boolean;
 
         /**
          * Defines that each material of the scene should keep up-to-date a map of referencing meshes for fast diposing
@@ -1235,7 +1235,7 @@ module BABYLON {
         /**
          * an optional map from Geometry Id to Geometry index in the 'geometries' array
          */
-        private geometriesById: Nullable<{ [id: string]: number | undefined }> = null;
+        private geometriesByUniqueId: Nullable<{ [uniqueId: string]: number | undefined }> = null;
 
         /**
          * Creates a new Scene
@@ -1271,11 +1271,11 @@ module BABYLON {
 
             this.setDefaultCandidateProviders();
 
-            if (options && options.useGeometryIdsMap === true) {
-                this.geometriesById = {};
+            if (options && options.useGeometryUniqueIdsMap === true) {
+                this.geometriesByUniqueId = {};
             }
 
-            this.useMaterialMeshMap = options && options.useGeometryIdsMap || false;
+            this.useMaterialMeshMap = options && options.useGeometryUniqueIdsMap || false;
             this.useClonedMeshhMap = options && options.useClonedMeshhMap || false;
 
             this._engine.onNewSceneAddedObservable.notifyObservers(this);
@@ -3354,8 +3354,8 @@ module BABYLON {
          * @param newGeometry The geometry to add
          */
         public addGeometry(newGeometry: Geometry): void {
-            if (this.geometriesById) {
-                this.geometriesById[newGeometry.id] = this.geometries.length;
+            if (this.geometriesByUniqueId) {
+                this.geometriesByUniqueId[newGeometry.uniqueId] = this.geometries.length;
             }
 
             this.geometries.push(newGeometry);
@@ -3623,29 +3623,29 @@ module BABYLON {
          * @return the geometry or null if none found.
          */
         public getGeometryByID(id: string): Nullable<Geometry> {
-            if (this.geometriesById) {
-                const index = this.geometriesById[id];
-                if (index !== undefined) {
+            for (var index = 0; index < this.geometries.length; index++) {
+                if (this.geometries[index].id === id) {
                     return this.geometries[index];
                 }
             }
-            else {
-                for (var index = 0; index < this.geometries.length; index++) {
-                    if (this.geometries[index].id === id) {
-                        return this.geometries[index];
-                    }
-                }
-            }
 
             return null;
         }
 
-        private _getGeometryByUniqueID(id: number): Nullable<Geometry> {
-            for (var index = 0; index < this.geometries.length; index++) {
-                if (this.geometries[index].uniqueId === id) {
+        private _getGeometryByUniqueID(uniqueId: number): Nullable<Geometry> {
+            if (this.geometriesByUniqueId) {
+                const index = this.geometriesByUniqueId[uniqueId];
+                if (index !== undefined) {
                     return this.geometries[index];
                 }
             }
+            else {
+                for (var index = 0; index < this.geometries.length; index++) {
+                    if (this.geometries[index].uniqueId === uniqueId) {
+                        return this.geometries[index];
+                    }
+                }
+            }
 
             return null;
         }
@@ -3680,8 +3680,8 @@ module BABYLON {
          */
         public removeGeometry(geometry: Geometry): boolean {
             let index;
-            if (this.geometriesById) {
-                index = this.geometriesById[geometry.id];
+            if (this.geometriesByUniqueId) {
+                index = this.geometriesByUniqueId[geometry.uniqueId];
                 if (index === undefined) {
                     return false;
                 }
@@ -3696,9 +3696,9 @@ module BABYLON {
             if (index !== this.geometries.length - 1) {
                 const lastGeometry = this.geometries[this.geometries.length - 1];
                 this.geometries[index] = lastGeometry;
-                if (this.geometriesById) {
-                    this.geometriesById[lastGeometry.id] = index;
-                    this.geometriesById[geometry.id] = undefined;
+                if (this.geometriesByUniqueId) {
+                    this.geometriesByUniqueId[lastGeometry.uniqueId] = index;
+                    this.geometriesByUniqueId[geometry.uniqueId] = undefined;
                 }
             }