sebavan 6 年之前
父节点
当前提交
f545d5261e

文件差异内容过多而无法显示
+ 51641 - 0
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>

文件差异内容过多而无法显示
+ 5550 - 5511
dist/preview release/babylon.d.ts


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/babylon.js


+ 110 - 62
dist/preview release/babylon.max.js

@@ -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(this.centerWorld) <= -this.radiusWorld) {
+                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(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();
@@ -102318,23 +102379,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");
@@ -102360,19 +102421,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

+ 110 - 62
dist/preview release/es6.js

@@ -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(this.centerWorld) <= -this.radiusWorld) {
+                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(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();
@@ -102285,23 +102346,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");
@@ -102327,19 +102388,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

文件差异内容过多而无法显示
+ 3 - 3
dist/preview release/inspector/babylon.inspector.bundle.js


+ 22 - 1
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): (sceneManager: SceneManager) => boolean;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 declare module BabylonViewer {
@@ -1558,6 +1558,20 @@ 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 {
@@ -1719,6 +1733,13 @@ declare module BabylonViewer {
     }
 }
 declare module BabylonViewer {
+    /**
+      * A (PBR) material will be extended using this function.
+      * This function will hold extra default configuration for the viewer, if not implemented in Babylon itself.
+      */
+    export class ExtendedMaterialLoaderPlugin implements ILoaderPlugin {
+        onMaterialLoaded(baseMaterial: BABYLON.Material): void;
+    }
 }
 declare module BabylonViewer {
     export interface ICameraConfiguration {

文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


文件差异内容过多而无法显示
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 27 - 2
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -985,13 +985,14 @@ 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): (sceneManager: SceneManager) => boolean;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 
@@ -1662,6 +1663,22 @@ 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';
@@ -1860,7 +1877,15 @@ declare module 'babylonjs-viewer/loader/plugins/applyMaterialConfig' {
 }
 
 declare module 'babylonjs-viewer/loader/plugins/extendedMaterialLoaderPlugin' {
-    
+    import { Material } from 'babylonjs';
+    import { ILoaderPlugin } from 'babylonjs-viewer/loader/plugins/loaderPlugin';
+    /**
+      * A (PBR) material will be extended using this function.
+      * This function will hold extra default configuration for the viewer, if not implemented in Babylon itself.
+      */
+    export class ExtendedMaterialLoaderPlugin implements ILoaderPlugin {
+        onMaterialLoaded(baseMaterial: Material): void;
+    }
 }
 
 declare module 'babylonjs-viewer/configuration/interfaces/cameraConfiguration' {

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

@@ -58,6 +58,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
@@ -83,6 +84,7 @@
 - Add support for setting renderingGroupId and creating instances to `AxesViewer` ([bghgary](https://github.com/bghgary))
 - 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))
+- Added per mesh culling strategy ([jerome](https://github.com/jbousquie))
 
 ### glTF Loader
 
@@ -143,6 +145,7 @@
 - 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
 

+ 15 - 3
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;
@@ -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 {

+ 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/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>

+ 11 - 2
src/Culling/boundingInfo.ts

@@ -156,17 +156,26 @@ import { BoundingSphere } from "./boundingSphere";
         /**
          * 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 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/boundingSphere.ts

@@ -108,12 +108,29 @@ import { Matrix, Vector3, Plane } from "../Maths/math";
          * @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;
         }
 

+ 42 - 3
src/Meshes/abstractMesh.ts

@@ -68,10 +68,40 @@ import { Constants } from "../Engines/constants";
         /** 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
@@ -102,7 +132,16 @@ import { Constants } from "../Engines/constants";
 
         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;
 
         /**

+ 24 - 16
src/Meshes/geometry.ts

@@ -530,7 +530,15 @@
             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);
+                    }
+                }
             }
         }
 
@@ -557,12 +565,10 @@
                 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();
         }
 
@@ -926,18 +932,20 @@
             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) {
+                    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 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;
+                        }
                     }
                 }
             }

+ 18 - 33
src/Misc/khronosTextureContainer.ts

@@ -93,25 +93,24 @@ import { InternalTexture } from "../Materials/Textures/internalTexture";
                 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) {
@@ -142,20 +141,6 @@ import { InternalTexture } from "../Materials/Textures/internalTexture";
             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

+ 26 - 26
src/scene.ts

@@ -98,10 +98,10 @@ import { Logger } from "./Misc/logger";
     /** 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
@@ -1270,7 +1270,7 @@ import { Logger } from "./Misc/logger";
         /**
          * 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
@@ -1306,11 +1306,11 @@ import { Logger } from "./Misc/logger";
 
             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);
@@ -3388,8 +3388,8 @@ import { Logger } from "./Misc/logger";
          * @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);
@@ -3657,29 +3657,29 @@ import { Logger } from "./Misc/logger";
          * @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;
         }
@@ -3714,8 +3714,8 @@ import { Logger } from "./Misc/logger";
          */
         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;
                 }
@@ -3730,9 +3730,9 @@ import { Logger } from "./Misc/logger";
             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;
                 }
             }