Procházet zdrojové kódy

Merge pull request #6069 from BabylonJS/master

nightly
David Catuhe před 6 roky
rodič
revize
246cd74c57
34 změnil soubory, kde provedl 6988 přidání a 5899 odebrání
  1. 785 671
      Playground/babylon.d.txt
  2. 797 674
      dist/preview release/babylon.d.ts
  3. 2 2
      dist/preview release/babylon.js
  4. 402 244
      dist/preview release/babylon.max.js
  5. 1 1
      dist/preview release/babylon.max.js.map
  6. 1635 1369
      dist/preview release/babylon.module.d.ts
  7. 39 39
      dist/preview release/gui/babylon.gui.js
  8. 1 1
      dist/preview release/gui/babylon.gui.js.map
  9. 1 1
      dist/preview release/packagesSizeBaseLine.json
  10. 1635 1369
      dist/preview release/viewer/babylon.module.d.ts
  11. 1 15
      dist/preview release/viewer/babylon.viewer.d.ts
  12. 34 22
      dist/preview release/viewer/babylon.viewer.js
  13. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  14. 1 18
      dist/preview release/viewer/babylon.viewer.module.d.ts
  15. 6 4
      dist/preview release/what's new.md
  16. 3 2
      src/Cameras/RigModes/vrRigMode.ts
  17. 2 2
      src/Cameras/VR/webVRCamera.ts
  18. 1241 1268
      src/Cameras/camera.ts
  19. 169 0
      src/Engines/Extensions/engine.multiview.ts
  20. 2 1
      src/Engines/Extensions/index.ts
  21. 22 53
      src/Engines/engine.ts
  22. 3 0
      src/Loading/Plugins/babylonFileLoader.ts
  23. 1 7
      src/Materials/Background/backgroundMaterial.ts
  24. 1 7
      src/Materials/PBR/pbrBaseMaterial.ts
  25. 40 0
      src/Materials/Textures/MultiviewRenderTarget.ts
  26. 1 38
      src/Materials/Textures/renderTargetTexture.ts
  27. 15 0
      src/Materials/materialHelper.ts
  28. 3 7
      src/Materials/standardMaterial.ts
  29. 93 0
      src/Misc/assetsManager.ts
  30. 2 1
      src/PostProcesses/index.ts
  31. 1 29
      src/PostProcesses/vrDistortionCorrectionPostProcess.ts
  32. 34 0
      src/PostProcesses/vrMultiviewToSingleviewPostProcess.ts
  33. 3 1
      src/assetContainer.ts
  34. 11 52
      src/scene.ts

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 785 - 671
Playground/babylon.d.txt


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 797 - 674
dist/preview release/babylon.d.ts


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 2 - 2
dist/preview release/babylon.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 402 - 244
dist/preview release/babylon.max.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 1
dist/preview release/babylon.max.js.map


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1635 - 1369
dist/preview release/babylon.module.d.ts


+ 39 - 39
dist/preview release/gui/babylon.gui.js

@@ -7,7 +7,7 @@
 		exports["babylonjs-gui"] = factory(require("babylonjs"));
 	else
 		root["BABYLON"] = root["BABYLON"] || {}, root["BABYLON"]["GUI"] = factory(root["BABYLON"]);
-})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__) {
+})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_Maths_math__) {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
@@ -355,7 +355,7 @@ module.exports = g;
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AdvancedDynamicTextureInstrumentation", function() { return AdvancedDynamicTextureInstrumentation; });
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__);
 
 /**
@@ -498,7 +498,7 @@ var AdvancedDynamicTextureInstrumentation = /** @class */ (function () {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AdvancedDynamicTexture", function() { return AdvancedDynamicTexture; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _controls_container__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./controls/container */ "./2D/controls/container.ts");
 /* harmony import */ var _style__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./style */ "./2D/style.ts");
@@ -1619,7 +1619,7 @@ var Button = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Checkbox", function() { return Checkbox; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
@@ -1800,7 +1800,7 @@ var Checkbox = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ColorPicker", function() { return ColorPicker; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _inputText__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./inputText */ "./2D/controls/inputText.ts");
@@ -3247,7 +3247,7 @@ var ColorPicker = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container", function() { return Container; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/logger */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/logger */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../measure */ "./2D/measure.ts");
@@ -3652,7 +3652,7 @@ var Container = /** @class */ (function (_super) {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Control", function() { return Control; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../measure */ "./2D/measure.ts");
@@ -6212,7 +6212,7 @@ var Grid = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Image", function() { return Image; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 
@@ -6987,7 +6987,7 @@ var InputPassword = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InputText", function() { return InputText; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
@@ -7996,7 +7996,7 @@ var InputText = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Line", function() { return Line; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
@@ -8264,7 +8264,7 @@ var Line = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiLine", function() { return MultiLine; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/abstractMesh */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/abstractMesh */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _multiLinePoint__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../multiLinePoint */ "./2D/multiLinePoint.ts");
@@ -8531,7 +8531,7 @@ var MultiLine = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RadioButton", function() { return RadioButton; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
@@ -8876,7 +8876,7 @@ var Rectangle = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScrollViewer", function() { return ScrollViewer; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Events/pointerEvents */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Events/pointerEvents */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _rectangle__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../rectangle */ "./2D/controls/rectangle.ts");
 /* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../grid */ "./2D/controls/grid.ts");
@@ -9967,7 +9967,7 @@ var SelectionPanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BaseSlider", function() { return BaseSlider; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../control */ "./2D/controls/control.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../valueAndUnit */ "./2D/valueAndUnit.ts");
@@ -10862,7 +10862,7 @@ var Slider = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StackPanel", function() { return StackPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
@@ -11120,7 +11120,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextWrapping", function() { return TextWrapping; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextBlock", function() { return TextBlock; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
@@ -11560,7 +11560,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KeyPropertySet", function() { return KeyPropertySet; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualKeyboard", function() { return VirtualKeyboard; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
 /* harmony import */ var _button__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./button */ "./2D/controls/button.ts");
@@ -11935,7 +11935,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Vector2WithInfo", function() { return Vector2WithInfo; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Matrix2D", function() { return Matrix2D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 
 
@@ -12159,7 +12159,7 @@ var Matrix2D = /** @class */ (function () {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Measure", function() { return Measure; });
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__);
 
 
@@ -12292,7 +12292,7 @@ var Measure = /** @class */ (function () {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiLinePoint", function() { return MultiLinePoint; });
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./valueAndUnit */ "./2D/valueAndUnit.ts");
 
@@ -12435,7 +12435,7 @@ var MultiLinePoint = /** @class */ (function () {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Style", function() { return Style; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./valueAndUnit */ "./2D/valueAndUnit.ts");
 
@@ -12742,7 +12742,7 @@ var ValueAndUnit = /** @class */ (function () {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AbstractButton3D", function() { return AbstractButton3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control3D */ "./3D/controls/control3D.ts");
 
@@ -12785,7 +12785,7 @@ var AbstractButton3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Button3D", function() { return Button3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _abstractButton3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./abstractButton3D */ "./3D/controls/abstractButton3D.ts");
 /* harmony import */ var _2D_advancedDynamicTexture__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../2D/advancedDynamicTexture */ "./2D/advancedDynamicTexture.ts");
@@ -12962,7 +12962,7 @@ var Button3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container3D", function() { return Container3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control3D */ "./3D/controls/control3D.ts");
 
@@ -13119,7 +13119,7 @@ var Container3D = /** @class */ (function (_super) {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Control3D", function() { return Control3D; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _vector3WithInfo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../vector3WithInfo */ "./3D/vector3WithInfo.ts");
 
@@ -13513,7 +13513,7 @@ var Control3D = /** @class */ (function () {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CylinderPanel", function() { return CylinderPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
@@ -13598,7 +13598,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HolographicButton", function() { return HolographicButton; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _button3D__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./button3D */ "./3D/controls/button3D.ts");
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2__);
 /* harmony import */ var _materials_fluentMaterial__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../materials/fluentMaterial */ "./3D/materials/fluentMaterial.ts");
 /* harmony import */ var _2D_controls_stackPanel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../2D/controls/stackPanel */ "./2D/controls/stackPanel.ts");
@@ -14074,7 +14074,7 @@ var MeshButton3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PlanePanel", function() { return PlanePanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
@@ -14129,7 +14129,7 @@ var PlanePanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScatterPanel", function() { return ScatterPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
@@ -14256,7 +14256,7 @@ var ScatterPanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SpherePanel", function() { return SpherePanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
@@ -14341,7 +14341,7 @@ var SpherePanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StackPanel3D", function() { return StackPanel3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 
@@ -14466,7 +14466,7 @@ var StackPanel3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VolumeBasedPanel", function() { return VolumeBasedPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 
@@ -14657,7 +14657,7 @@ var VolumeBasedPanel = /** @class */ (function (_super) {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GUI3DManager", function() { return GUI3DManager; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _controls_container3D__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./controls/container3D */ "./3D/controls/container3D.ts");
 
@@ -14924,7 +14924,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FluentMaterialDefines", function() { return FluentMaterialDefines; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FluentMaterial", function() { return FluentMaterial; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/decorators */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/decorators */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _shaders_fluent_vertex__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./shaders/fluent.vertex */ "./3D/materials/shaders/fluent.vertex.ts");
 /* harmony import */ var _shaders_fluent_fragment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./shaders/fluent.fragment */ "./3D/materials/shaders/fluent.fragment.ts");
@@ -15246,7 +15246,7 @@ __webpack_require__.r(__webpack_exports__);
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fluentPixelShader", function() { return fluentPixelShader; });
-/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__);
 
 var name = 'fluentPixelShader';
@@ -15268,7 +15268,7 @@ var fluentPixelShader = { name: name, shader: shader };
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fluentVertexShader", function() { return fluentVertexShader; });
-/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__);
 
 var name = 'fluentVertexShader';
@@ -15291,7 +15291,7 @@ var fluentVertexShader = { name: name, shader: shader };
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Vector3WithInfo", function() { return Vector3WithInfo; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 
 
@@ -15585,14 +15585,14 @@ if (typeof globalObject !== "undefined") {
 
 /***/ }),
 
-/***/ "babylonjs/Misc/observable":
+/***/ "babylonjs/Maths/math":
 /*!****************************************************************************************************!*\
   !*** external {"root":"BABYLON","commonjs":"babylonjs","commonjs2":"babylonjs","amd":"babylonjs"} ***!
   \****************************************************************************************************/
 /*! no static exports found */
 /***/ (function(module, exports) {
 
-module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__;
+module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Maths_math__;
 
 /***/ })
 

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 1
dist/preview release/gui/babylon.gui.js.map


+ 1 - 1
dist/preview release/packagesSizeBaseLine.json

@@ -1 +1 @@
-{"engineOnly":309267,"sceneOnly":551685,"minGridMaterial":674918,"minStandardMaterial":773773}
+{"engineOnly":308499,"sceneOnly":510323,"minGridMaterial":633781,"minStandardMaterial":757466}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1635 - 1369
dist/preview release/viewer/babylon.module.d.ts


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

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

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 34 - 22
dist/preview release/viewer/babylon.viewer.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


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

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

+ 6 - 4
dist/preview release/what's new.md

@@ -8,8 +8,7 @@
 - Added [support for AmmoJS](https://doc.babylonjs.com/how_to/using_the_physics_engine) as a physics plugin (Composite objects, motors, joints) ([TrevorDev](https://github.com/TrevorDev))
   - Added support for soft bodies, which are 3D softbody, 2D cloth and 1D rope, in Ammo physics plugin. [Doc](https://doc.babylonjs.com/how_to/soft_bodies) ([JohnK](https://github.com/BabylonJSGuide))
   - Added support for [Convex Hull Impostor][https://github.com/kripken/ammo.js/blob/master/bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.h] using Ammo.js plugin ([MackeyK24](https://github.com/mackeyk24))
-  - Added customShaderNameResolve to PBRMaterialBase to allow subclasses to specify custom shader information [MackeyK24](https://github.com/mackeyk24))
-  - Added PBRCustomMaterial to material library to allow easy subclassing of PBR materials [MackeyK24](https://github.com/mackeyk24))  
+  - Added AmmoJSPlugin scene file loader [MackeyK24](https://github.com/mackeyk24))  
 - Added support for [WebXR](https://doc.babylonjs.com/how_to/webxr) ([TrevorDev](https://github.com/TrevorDev))
   - Add customAnimationFrameRequester to allow sessions to hook into engine's render loop ([TrevorDev](https://github.com/TrevorDev))
   - camera customDefaultRenderTarget to allow cameras to render to a custom render target (eg. xr framebuffer) instead of the canvas ([TrevorDev](https://github.com/TrevorDev))
@@ -29,7 +28,7 @@
   - InvalidateRect added to AdvancedDynamicTexture to improve perf for heavily populated GUIs, works with shadows ([TrevorDev](https://github.com/TrevorDev)) **** NEED DEMO or DOC LINK)
 - Migrated the code to modules and deploy [ES6 npm packages](https://doc.babylonjs.com/features/es6_support) ([Sebavan](https://github.com/Sebavan))
 - Added `TrailMesh` class. Credit to furcatomasz ([danjpar](https://github.com/danjpar)) **** NEED DEMO or DOC LINK)
-- Support rendering to a Multiview outputRenderTargetTexture to improve performance for XR scenarios ([TrevorDev](https://github.com/TrevorDev))
+- Support rendering to a Multiview outputRenderTargetTexture with multiview engine component to improve performance for XR scenarios ([TrevorDev](https://github.com/TrevorDev))
 - PBR:
   - Added Inspector Debug Mode ([Sebavan](https://github.com/Sebavan)) **** NEED DEMO or DOC LINK)
   - Added Smith Height Correlated Visibility term to PBR ([Sebavan](https://github.com/Sebavan)) **** NEED DEMO or DOC LINK)
@@ -131,6 +130,8 @@
 - Observables can now make observers top or bottom priority ([TrevorDev](https://github.com/TrevorDev))
 - Mesh outline no longer is shown through the mesh when it's transparent ([TrevorDev](https://github.com/TrevorDev))
 - DeviceOrientationCamera will no longer be modified by mouse input if the orientation sensor is active ([TrevorDev](https://github.com/TrevorDev))
+- Added customShaderNameResolve to PBRMaterialBase to allow subclasses to specify custom shader information [MackeyK24](https://github.com/mackeyk24))
+- Added PBRCustomMaterial to material library to allow easy subclassing of PBR materials [MackeyK24](https://github.com/mackeyk24))    
 
 ### OBJ Loader
 - Add color vertex support (not part of standard) ([brianzinn](https://github.com/brianzinn))
@@ -147,6 +148,7 @@
   - Skinned meshes now set an override mesh instead of reparenting to the `__root__` transform node
   - Loaded bones are linked with the transform node created for the corresponding glTF node
 - Add `EquiRectangularCubeTexture` class to enable the usage of browser-canvas supported images as `CubeTexture`'s ([Dennis Dervisis](https://github.com/ddervisis))
+- Add `EquiRectangularCubeTextureAssetTask` to be able to load `EquiRectangularCubeTextures`s via Asset Manager ([Dennis Dervisis](https://github.com/ddervisis))
 
 ### glTF Serializer
 
@@ -205,7 +207,7 @@
 - Tools.CreateScreenshot stopped working ([TrevorDev](https://github.com/TrevorDev))
 - Inspector showing duplicate nodes when attached to gizmo ([TrevorDev](https://github.com/TrevorDev))
 - Add missing dependencies for files to support including them from a direct path (eg. import "@babylonjs/core/Helpers/sceneHelpers";) ([TrevorDev](https://github.com/TrevorDev))
-- AssetContainer should not dispose objects it doesn't contain, Support for environmentTexture ([TrevorDev](https://github.com/TrevorDev))
+- AssetContainer should not dispose objects it doesn't contain. Support for environmentTexture add/remove ([TrevorDev](https://github.com/TrevorDev))
 - Fix `mesh.visibility` not working properly when certain material properties are set that changes the interpretation of alpha (e.g. refraction, specular over alpha, etc.) ([bghgary](https://github.com/bghgary))
 - Fix material and texture leak when loading/removing GLTF with AssetContainer ([TrevorDev](https://github.com/TrevorDev))
 

+ 3 - 2
src/Cameras/RigModes/vrRigMode.ts

@@ -1,6 +1,7 @@
 import { Camera } from "../camera";
 import { Matrix, Viewport } from "../../Maths/math";
-import { VRDistortionCorrectionPostProcess, VRMultiviewToSingleview } from "../../PostProcesses/vrDistortionCorrectionPostProcess";
+import { VRDistortionCorrectionPostProcess } from "../../PostProcesses/vrDistortionCorrectionPostProcess";
+import { VRMultiviewToSingleviewPostProcess } from '../../PostProcesses/vrMultiviewToSingleviewPostProcess';
 import { VRCameraMetrics } from "../VR/vrCameraMetrics";
 import { Logger } from '../../Misc/logger';
 
@@ -30,7 +31,7 @@ Camera._setVRRigMode = function(camera: Camera, rigParams: any) {
             metrics.multiviewEnabled = false;
         }else {
             camera._useMultiviewToSingleView = true;
-            camera._rigPostProcess = new VRMultiviewToSingleview("VRMultiviewToSingleview", camera, metrics.postProcessScaleFactor);
+            camera._rigPostProcess = new VRMultiviewToSingleviewPostProcess("VRMultiviewToSingleview", camera, metrics.postProcessScaleFactor);
         }
     }
 

+ 2 - 2
src/Cameras/VR/webVRCamera.ts

@@ -14,7 +14,7 @@ import { AbstractMesh } from "../../Meshes/abstractMesh";
 import { Ray } from "../../Culling/ray";
 import { HemisphericLight } from "../../Lights/hemisphericLight";
 import { Logger } from '../../Misc/logger';
-import { VRMultiviewToSingleview } from '../../PostProcesses/vrDistortionCorrectionPostProcess';
+import { VRMultiviewToSingleviewPostProcess } from '../../PostProcesses/vrMultiviewToSingleviewPostProcess';
 
 // Side effect import to define the stereoscopic mode.
 import "../RigModes/webVRRigMode";
@@ -289,7 +289,7 @@ export class WebVRFreeCamera extends FreeCamera implements PoseControlled {
                 this._useMultiviewToSingleView = false;
             }else {
                 this._useMultiviewToSingleView = true;
-                this._rigPostProcess = new VRMultiviewToSingleview("VRMultiviewToSingleview", this, 1.0);
+                this._rigPostProcess = new VRMultiviewToSingleviewPostProcess("VRMultiviewToSingleview", this, 1.0);
             }
         }
 

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1241 - 1268
src/Cameras/camera.ts


+ 169 - 0
src/Engines/Extensions/engine.multiview.ts

@@ -0,0 +1,169 @@
+import { Camera } from "../../Cameras/camera";
+import { Engine } from "../../Engines/engine";
+import { Scene } from "../../scene";
+import { InternalTexture } from '../../Materials/Textures/internalTexture';
+import { Nullable } from '../../types';
+import { RenderTargetTexture } from '../../Materials/Textures/renderTargetTexture';
+import { Matrix, Tmp, Frustum } from '../../Maths/math';
+import { UniformBuffer } from '../../Materials/uniformBuffer';
+import { MultiviewRenderTarget } from '../../Materials/Textures/MultiviewRenderTarget';
+
+declare module "../../Engines/engine" {
+    export interface Engine {
+        /**
+         * Creates a new multiview render target
+         * @param width defines the width of the texture
+         * @param height defines the height of the texture
+         * @returns the created multiview texture
+         */
+        createMultiviewRenderTargetTexture(width: number, height: number): InternalTexture;
+
+        /**
+         * Binds a multiview framebuffer to be drawn to
+         * @param multiviewTexture texture to bind
+         */
+        bindMultiviewFramebuffer(multiviewTexture: InternalTexture): void;
+    }
+}
+
+Engine.prototype.createMultiviewRenderTargetTexture = function(width: number, height: number) {
+    var gl = this._gl;
+
+    if (!this.getCaps().multiview) {
+        throw "Multiview is not supported";
+    }
+
+    var internalTexture = new InternalTexture(this, InternalTexture.DATASOURCE_UNKNOWN, true);
+    internalTexture.width = width;
+    internalTexture.height = height;
+    internalTexture._framebuffer = gl.createFramebuffer();
+
+    internalTexture._colorTextureArray = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D_ARRAY, internalTexture._colorTextureArray);
+    (gl as any).texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, 2);
+
+    internalTexture._depthStencilTextureArray = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D_ARRAY, internalTexture._depthStencilTextureArray);
+    (gl as any).texStorage3D(gl.TEXTURE_2D_ARRAY, 1, (gl as any).DEPTH32F_STENCIL8, width, height, 2);
+    internalTexture.isReady = true;
+    return internalTexture;
+};
+
+Engine.prototype.bindMultiviewFramebuffer = function(multiviewTexture: InternalTexture) {
+    var gl: any = this._gl;
+    var ext = this.getCaps().multiview;
+
+    this.bindFramebuffer(multiviewTexture, undefined, undefined, undefined, true);
+    gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, multiviewTexture._framebuffer);
+    if (multiviewTexture._colorTextureArray && multiviewTexture._depthStencilTextureArray) {
+        ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, multiviewTexture._colorTextureArray, 0, 0, 2);
+        ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, multiviewTexture._depthStencilTextureArray, 0, 0, 2);
+    } else {
+        throw "Invalid multiview frame buffer";
+    }
+};
+
+declare module "../../Cameras/camera" {
+    export interface Camera {
+        /**
+         * @hidden
+         * For cameras that cannot use multiview images to display directly. (e.g. webVR camera will render to multiview texture, then copy to each eye texture and go from there)
+         */
+        _useMultiviewToSingleView: boolean;
+        /**
+         * @hidden
+         * For cameras that cannot use multiview images to display directly. (e.g. webVR camera will render to multiview texture, then copy to each eye texture and go from there)
+         */
+        _multiviewTexture: Nullable<RenderTargetTexture>;
+
+        /**
+         * @hidden
+         * ensures the multiview texture of the camera exists and has the specified width/height
+         * @param width height to set on the multiview texture
+         * @param height width to set on the multiview texture
+         */
+        _resizeOrCreateMultiviewTexture(width: number, height: number): void;
+    }
+}
+
+Camera.prototype._useMultiviewToSingleView = false;
+
+Camera.prototype._multiviewTexture = null;
+
+Camera.prototype._resizeOrCreateMultiviewTexture = function(width: number, height: number) {
+    if (!this._multiviewTexture) {
+        this._multiviewTexture = new MultiviewRenderTarget(this.getScene(), {width: width, height: height});
+    }else if (this._multiviewTexture.getRenderWidth() != width || this._multiviewTexture.getRenderHeight() != height) {
+        this._multiviewTexture.dispose();
+        this._multiviewTexture = new MultiviewRenderTarget(this.getScene(), {width: width, height: height});
+    }
+};
+
+declare module "../../scene" {
+    export interface Scene {
+        /** @hidden */
+        _transformMatrixR: Matrix;
+        /** @hidden */
+        _multiviewSceneUbo: Nullable<UniformBuffer>;
+        /** @hidden */
+        _createMultiviewUbo(): void;
+        /** @hidden */
+        _updateMultiviewUbo(viewR?: Matrix, projectionR?: Matrix): void;
+        /** @hidden */
+        _renderMultiviewToSingleView(camera: Camera): void;
+    }
+}
+
+Scene.prototype._transformMatrixR = Matrix.Zero();
+Scene.prototype._multiviewSceneUbo = null;
+Scene.prototype._createMultiviewUbo = function() {
+    this._multiviewSceneUbo = new UniformBuffer(this.getEngine(), undefined, true);
+    this._multiviewSceneUbo.addUniform("viewProjection", 16);
+    this._multiviewSceneUbo.addUniform("viewProjectionR", 16);
+    this._multiviewSceneUbo.addUniform("view", 16);
+};
+Scene.prototype._updateMultiviewUbo = function(viewR?: Matrix, projectionR?: Matrix) {
+    if (viewR && projectionR) {
+        viewR.multiplyToRef(projectionR, this._transformMatrixR);
+    }
+
+    if (viewR && projectionR) {
+        viewR.multiplyToRef(projectionR, Tmp.Matrix[0]);
+        Frustum.GetRightPlaneToRef(Tmp.Matrix[0], this._frustumPlanes[3]); // Replace right plane by second camera right plane
+    }
+
+    if (this._multiviewSceneUbo) {
+        this._multiviewSceneUbo.updateMatrix("viewProjection", this.getTransformMatrix());
+        this._multiviewSceneUbo.updateMatrix("viewProjectionR", this._transformMatrixR);
+        this._multiviewSceneUbo.updateMatrix("view", this._viewMatrix);
+        this._multiviewSceneUbo.update();
+    }
+};
+Scene.prototype._renderMultiviewToSingleView = function(camera: Camera) {
+    // Multiview is only able to be displayed directly for API's such as webXR
+    // This displays a multiview image by rendering to the multiview image and then
+    // copying the result into the sub cameras instead of rendering them and proceeding as normal from there
+
+    // Render to a multiview texture
+    camera._resizeOrCreateMultiviewTexture(
+        (camera._rigPostProcess && camera._rigPostProcess && camera._rigPostProcess.width > 0) ? camera._rigPostProcess.width / 2 : this.getEngine().getRenderWidth(true) / 2,
+        (camera._rigPostProcess && camera._rigPostProcess && camera._rigPostProcess.height > 0) ? camera._rigPostProcess.height : this.getEngine().getRenderHeight(true)
+    );
+    if (!this._multiviewSceneUbo) {
+        this._createMultiviewUbo();
+    }
+    camera.outputRenderTarget = camera._multiviewTexture;
+    this._renderForCamera(camera);
+    camera.outputRenderTarget = null;
+
+    // Consume the multiview texture through a shader for each eye
+    for (var index = 0; index < camera._rigCameras.length; index++) {
+        var engine = this.getEngine();
+        this._activeCamera = camera._rigCameras[index];
+        engine.setViewport(this._activeCamera.viewport);
+        if (this.postProcessManager) {
+            this.postProcessManager._prepareFrame();
+            this.postProcessManager._finalizeFrame(this._activeCamera.isIntermediate);
+        }
+    }
+};

+ 2 - 1
src/Engines/Extensions/index.ts

@@ -1,2 +1,3 @@
 export * from "./engine.occlusionQuery";
-export * from "./engine.transformFeedback";
+export * from "./engine.transformFeedback";
+export * from "./engine.multiview";

+ 22 - 53
src/Engines/engine.ts

@@ -243,12 +243,17 @@ export interface IDisplayChangedEventArgs {
 export class Engine {
     /** Use this array to turn off some WebGL2 features on known buggy browsers version */
     public static ExceptionList = [
-        { key: "Chrome/63.0", capture: "63\\.0\\.3239\\.(\\d+)", captureConstraint: 108, targets: ["uniformBuffer"] },
-        { key: "Firefox/58", capture: null, captureConstraint: null, targets: ["uniformBuffer"] },
-        { key: "Firefox/59", capture: null, captureConstraint: null, targets: ["uniformBuffer"] },
+        { key: "Chrome\/63\.0", capture: "63\\.0\\.3239\\.(\\d+)", captureConstraint: 108, targets: ["uniformBuffer"] },
+        { key: "Firefox\/58", capture: null, captureConstraint: null, targets: ["uniformBuffer"] },
+        { key: "Firefox\/59", capture: null, captureConstraint: null, targets: ["uniformBuffer"] },
         { key: "Macintosh", capture: null, captureConstraint: null, targets: ["textureBindingOptimization"] },
         { key: "iPhone", capture: null, captureConstraint: null, targets: ["textureBindingOptimization"] },
-        { key: "iPad", capture: null, captureConstraint: null, targets: ["textureBindingOptimization"] }
+        { key: "iPad", capture: null, captureConstraint: null, targets: ["textureBindingOptimization"] },
+        { key: "Chrome\/72.+?Mobile", capture: null, captureConstraint: null, targets: ["vao"] },
+        { key: "Chrome\/73.+?Mobile", capture: null, captureConstraint: null, targets: ["vao"] },
+        { key: "Chrome\/74.+?Mobile", capture: null, captureConstraint: null, targets: ["vao"] },
+        { key: "Mac OS.+Chrome\/71", capture: null, captureConstraint: null, targets: ["vao"] },
+        { key: "Mac OS.+Chrome\/72", capture: null, captureConstraint: null, targets: ["vao"] }
     ];
 
     /** Gets the list of created engines */
@@ -856,6 +861,11 @@ export class Engine {
         return this._performanceMonitor;
     }
 
+    /**
+     * Gets or sets a boolean indicating that vertex array object must be disabled even if they are supported
+     */
+    public disableVertexArrayObjects = false;
+
     // States
     /** @hidden */
     protected _depthCullingState = new _DepthCullingState();
@@ -1054,8 +1064,9 @@ export class Engine {
                 for (var exception of Engine.ExceptionList) {
                     let key = exception.key;
                     let targets = exception.targets;
+                    let check = new RegExp(key);
 
-                    if (ua.indexOf(key) > -1) {
+                    if (check.test(ua)) {
                         if (exception.capture && exception.captureConstraint) {
                             let capture = exception.capture;
                             let constraint = exception.captureConstraint;
@@ -1076,6 +1087,9 @@ export class Engine {
                                 case "uniformBuffer":
                                     this.disableUniformBuffers = true;
                                     break;
+                                case "vao":
+                                    this.disableVertexArrayObjects = true;
+                                    break;
                                 case "textureBindingOptimization":
                                     this.disableTextureBindingOptimization = true;
                                     break;
@@ -1491,7 +1505,9 @@ export class Engine {
         }
 
         // Vertex array object
-        if (this._webGLVersion > 1) {
+        if (this.disableVertexArrayObjects) {
+            this._caps.vertexArrayObject = false;
+        } else if (this._webGLVersion > 1) {
             this._caps.vertexArrayObject = true;
         } else {
             var vertexArrayObjectExtension = this._gl.getExtension('OES_vertex_array_object');
@@ -5614,53 +5630,6 @@ export class Engine {
     }
 
     /**
-     * Creates a new multiview render target
-     * @param width defines the width of the texture
-     * @param height defines the height of the texture
-     * @returns the created multiview texture
-     */
-    public createMultiviewRenderTargetTexture(width: number, height: number) {
-        var gl = this._gl;
-
-        if (!this.getCaps().multiview) {
-            throw "Multiview is not supported";
-        }
-
-        var internalTexture = new InternalTexture(this, InternalTexture.DATASOURCE_UNKNOWN, true);
-        internalTexture.width = width;
-        internalTexture.height = height;
-        internalTexture._framebuffer = gl.createFramebuffer();
-
-        internalTexture._colorTextureArray = gl.createTexture();
-        gl.bindTexture(gl.TEXTURE_2D_ARRAY, internalTexture._colorTextureArray);
-        (gl as any).texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, 2);
-
-        internalTexture._depthStencilTextureArray = gl.createTexture();
-        gl.bindTexture(gl.TEXTURE_2D_ARRAY, internalTexture._depthStencilTextureArray);
-        (gl as any).texStorage3D(gl.TEXTURE_2D_ARRAY, 1, (gl as any).DEPTH32F_STENCIL8, width, height, 2);
-        internalTexture.isReady = true;
-        return internalTexture;
-    }
-
-    /**
-     * Binds a multiview framebuffer to be drawn to
-     * @param multiviewTexture texture to bind
-     */
-    public bindMultiviewFramebuffer(multiviewTexture: InternalTexture) {
-        var gl: any = this._gl;
-        var ext = this.getCaps().multiview;
-
-        this.bindFramebuffer(multiviewTexture, undefined, undefined, undefined, true);
-        gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, multiviewTexture._framebuffer);
-        if (multiviewTexture._colorTextureArray && multiviewTexture._depthStencilTextureArray) {
-            ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, multiviewTexture._colorTextureArray, 0, 0, 2);
-            ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, multiviewTexture._depthStencilTextureArray, 0, 0, 2);
-        } else {
-            throw "Invalid multiview frame buffer";
-        }
-    }
-
-    /**
      * Creates a new render target cube texture
      * @param size defines the size of the texture
      * @param options defines the options used to create the texture

+ 3 - 0
src/Loading/Plugins/babylonFileLoader.ts

@@ -25,6 +25,7 @@ import { Skeleton } from "../../Bones/skeleton";
 import { MorphTargetManager } from "../../Morph/morphTargetManager";
 import { CannonJSPlugin } from "../../Physics/Plugins/cannonJSPlugin";
 import { OimoJSPlugin } from "../../Physics/Plugins/oimoJSPlugin";
+import { AmmoJSPlugin } from "../../Physics/Plugins/ammoJSPlugin";
 import { ReflectionProbe } from "../../Probes/reflectionProbe";
 import { _TypeStore } from '../../Misc/typeStore';
 
@@ -591,6 +592,8 @@ SceneLoader.RegisterPlugin({
                     physicsPlugin = new CannonJSPlugin();
                 } else if (parsedData.physicsEngine === "oimo") {
                     physicsPlugin = new OimoJSPlugin();
+                } else if (parsedData.physicsEngine === "ammo") {
+                    physicsPlugin = new AmmoJSPlugin();
                 }
                 log = "\tPhysics engine " + (parsedData.physicsEngine ? parsedData.physicsEngine : "oimo") + " enabled\n";
                 //else - default engine, which is currently oimo

+ 1 - 7
src/Materials/Background/backgroundMaterial.ts

@@ -677,13 +677,7 @@ export class BackgroundMaterial extends PushMaterial {
         defines._needNormals = true;
 
         // Multiview
-        if (scene.activeCamera) {
-            var previousMultiview = defines.MULTIVIEW;
-            defines.MULTIVIEW = (scene.activeCamera.outputRenderTarget !== null && scene.activeCamera.outputRenderTarget.getViewCount() > 1);
-            if (defines.MULTIVIEW != previousMultiview) {
-                defines.markAsUnprocessed();
-            }
-        }
+        MaterialHelper.PrepareDefinesForMultiview(scene, defines);
 
         // Textures
         if (defines._areTexturesDirty) {

+ 1 - 7
src/Materials/PBR/pbrBaseMaterial.ts

@@ -1254,13 +1254,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
         defines._needNormals = true;
 
         // Multiview
-        if (scene.activeCamera) {
-            var previousMultiview = defines.MULTIVIEW;
-            defines.MULTIVIEW = (scene.activeCamera.outputRenderTarget !== null && scene.activeCamera.outputRenderTarget.getViewCount() > 1);
-            if (defines.MULTIVIEW != previousMultiview) {
-                defines.markAsUnprocessed();
-            }
-        }
+        MaterialHelper.PrepareDefinesForMultiview(scene, defines);
 
         // Textures
         defines.METALLICWORKFLOW = this.isMetallicWorkflow();

+ 40 - 0
src/Materials/Textures/MultiviewRenderTarget.ts

@@ -0,0 +1,40 @@
+import { RenderTargetTexture } from '../Textures/renderTargetTexture';
+import { Scene } from '../../scene';
+import { InternalTexture } from '../Textures/internalTexture';
+
+/**
+ * Renders to multiple views with a single draw call
+ * @see https://www.khronos.org/registry/webgl/extensions/WEBGL_multiview/
+ */
+export class MultiviewRenderTarget extends RenderTargetTexture {
+    /**
+     * Creates a multiview render target
+     * @param scene scene used with the render target
+     * @param size the size of the render target (used for each view)
+     */
+    constructor(scene: Scene, size: number | { width: number, height: number } | { ratio: number } = 512) {
+        super("multiview rtt", size, scene, false, true, InternalTexture.DATASOURCE_UNKNOWN, false, undefined, false, false, true, undefined, true);
+        var internalTexture = scene.getEngine().createMultiviewRenderTargetTexture(this.getRenderWidth(), this.getRenderHeight());
+        internalTexture.isMultiview = true;
+        this._texture = internalTexture;
+    }
+
+    /**
+     * @hidden
+     * @param faceIndex the face index, if its a cube texture
+     */
+    public _bindFrameBuffer(faceIndex: number = 0) {
+        if (!this._texture) {
+            return;
+        }
+        this.getScene()!.getEngine().bindMultiviewFramebuffer(this._texture);
+    }
+
+    /**
+     * Gets the number of views the corresponding to the texture (eg. a MultiviewRenderTarget will have > 1)
+     * @returns the view count
+     */
+    public getViewCount() {
+        return 2;
+    }
+}

+ 1 - 38
src/Materials/Textures/renderTargetTexture.ts

@@ -1001,41 +1001,4 @@ export class RenderTargetTexture extends Texture {
 
 Texture._CreateRenderTargetTexture = (name: string, renderTargetSize: number, scene: Scene, generateMipMaps: boolean) => {
     return new RenderTargetTexture(name, renderTargetSize, scene, generateMipMaps);
-};
-
-/**
- * Renders to multiple views with a single draw call
- * @see https://www.khronos.org/registry/webgl/extensions/WEBGL_multiview/
- */
-export class MultiviewRenderTarget extends RenderTargetTexture {
-    /**
-     * Creates a multiview render target
-     * @param scene scene used with the render target
-     * @param size the size of the render target (used for each view)
-     */
-    constructor(scene: Scene, size: number | { width: number, height: number } | { ratio: number } = 512) {
-        super("multiview rtt", size, scene, false, true, InternalTexture.DATASOURCE_UNKNOWN, false, undefined, false, false, true, undefined, true);
-        var internalTexture = scene.getEngine().createMultiviewRenderTargetTexture(this.getRenderWidth(), this.getRenderHeight());
-        internalTexture.isMultiview = true;
-        this._texture = internalTexture;
-    }
-
-    /**
-     * @hidden
-     * @param faceIndex the face index, if its a cube texture
-     */
-    public _bindFrameBuffer(faceIndex: number = 0) {
-        if (!this._texture) {
-            return;
-        }
-        this.getScene()!.getEngine().bindMultiviewFramebuffer(this._texture);
-    }
-
-    /**
-     * Gets the number of views the corresponding to the texture (eg. a MultiviewRenderTarget will have > 1)
-     * @returns the view count
-     */
-    public getViewCount() {
-        return 2;
-    }
-}
+};

+ 15 - 0
src/Materials/materialHelper.ts

@@ -229,6 +229,21 @@ export class MaterialHelper {
     }
 
     /**
+     * Prepares the defines related to multiview
+     * @param scene The scene we are intending to draw
+     * @param defines The defines to update
+     */
+    public static PrepareDefinesForMultiview(scene: Scene, defines: any) {
+        if (scene.activeCamera) {
+            var previousMultiview = defines.MULTIVIEW;
+            defines.MULTIVIEW = (scene.activeCamera.outputRenderTarget !== null && scene.activeCamera.outputRenderTarget.getViewCount() > 1);
+            if (defines.MULTIVIEW != previousMultiview) {
+                defines.markAsUnprocessed();
+            }
+        }
+    }
+
+    /**
      * Prepares the defines related to the light information passed in parameter
      * @param scene The scene we are intending to draw
      * @param mesh The mesh the effect is compiling for

+ 3 - 7
src/Materials/standardMaterial.ts

@@ -793,13 +793,9 @@ export class StandardMaterial extends PushMaterial {
 
         // Lights
         defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, true, this._maxSimultaneousLights, this._disableLighting);
-        if (scene.activeCamera) {
-            var previousMultiview = defines.MULTIVIEW;
-            defines.MULTIVIEW = (scene.activeCamera.outputRenderTarget !== null && scene.activeCamera.outputRenderTarget.getViewCount() > 1);
-            if (defines.MULTIVIEW != previousMultiview) {
-                defines.markAsUnprocessed();
-            }
-        }
+
+        // Multiview
+        MaterialHelper.PrepareDefinesForMultiview(scene, defines);
 
         // Textures
         if (defines._areTexturesDirty) {

+ 93 - 0
src/Misc/assetsManager.ts

@@ -9,6 +9,7 @@ import { BaseTexture } from "../Materials/Textures/baseTexture";
 import { Texture } from "../Materials/Textures/texture";
 import { CubeTexture } from "../Materials/Textures/cubeTexture";
 import { HDRCubeTexture } from "../Materials/Textures/hdrCubeTexture";
+import { EquiRectangularCubeTexture } from "../Materials/Textures/equiRectangularCubeTexture";
 import { Logger } from "../Misc/logger";
 import { AnimationGroup } from '../Animations/animationGroup';
 
@@ -687,6 +688,80 @@ export class HDRCubeTextureAssetTask extends AbstractAssetTask implements ITextu
 }
 
 /**
+ * Define a task used by AssetsManager to load Equirectangular cube textures
+ */
+export class EquiRectangularCubeTextureAssetTask extends AbstractAssetTask implements ITextureAssetTask<EquiRectangularCubeTexture> {
+    /**
+     * Gets the loaded texture
+     */
+    public texture: EquiRectangularCubeTexture;
+
+    /**
+     * Callback called when the task is successful
+     */
+    public onSuccess: (task: EquiRectangularCubeTextureAssetTask) => void;
+    /**
+     * Callback called when the task is successful
+     */
+    public onError: (task: EquiRectangularCubeTextureAssetTask, message?: string, exception?: any) => void;
+
+    /**
+     * Creates a new EquiRectangularCubeTextureAssetTask object
+     * @param name defines the name of the task
+     * @param url defines the location of the file to load
+     * @param size defines the desired size (the more it increases the longer the generation will be)
+     * If the size is omitted this implies you are using a preprocessed cubemap.
+     * @param noMipmap defines if mipmaps should not be generated (default is false)
+     * @param gammaSpace specifies if the texture will be used in gamma or linear space
+     * (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space)
+     * (default is true)
+     */
+    constructor(
+        /**
+         * Defines the name of the task
+         */
+        public name: string,
+        /**
+         * Defines the location of the file to load
+         */
+        public url: string,
+        /**
+         * Defines the desired size (the more it increases the longer the generation will be)
+         */
+        public size: number,
+        /**
+         * Defines if mipmaps should not be generated (default is false)
+         */
+        public noMipmap: boolean = false,
+        /**
+         * Specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space,
+         * but the standard material would require them in Gamma space) (default is true)
+         */
+        public gammaSpace: boolean = true) {
+        super(name);
+    }
+
+    /**
+     * Execute the current task
+     * @param scene defines the scene where you want your assets to be loaded
+     * @param onSuccess is a callback called when the task is successfully executed
+     * @param onError is a callback called if an error occurs
+     */
+    public runTask(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void): void {
+
+        const onload = () => {
+            onSuccess();
+        };
+
+        const onerror = (message?: string, exception?: any) => {
+            onError(message, exception);
+        };
+
+        this.texture = new EquiRectangularCubeTexture(this.url, scene, this.size, this.noMipmap, this.gammaSpace, onload, onerror);
+    }
+}
+
+/**
  * This class can be used to easily import assets into a scene
  * @see http://doc.babylonjs.com/how_to/how_to_use_assetsmanager
  */
@@ -858,6 +933,24 @@ export class AssetsManager {
     }
 
     /**
+     *
+     * Add a EquiRectangularCubeTextureAssetTask to the list of active tasks
+     * @param taskName defines the name of the new task
+     * @param url defines the url of the file to load
+     * @param size defines the size you want for the cubemap (can be null)
+     * @param noMipmap defines if the texture must not receive mipmaps (false by default)
+     * @param gammaSpace Specifies if the texture will be used in gamma or linear space
+     * (the PBR material requires those textures in linear space, but the standard material would require them in Gamma space)
+     * @returns a new EquiRectangularCubeTextureAssetTask object
+     */
+    public addEquiRectangularCubeTextureAssetTask(taskName: string, url: string, size: number, noMipmap = false, gammaSpace = true): EquiRectangularCubeTextureAssetTask {
+        const task = new EquiRectangularCubeTextureAssetTask(taskName, url, size, noMipmap, gammaSpace);
+        this._tasks.push(task);
+
+        return task;
+    }
+
+    /**
      * Remove a task from the assets manager.
      * @param task the task to remove
      */

+ 2 - 1
src/PostProcesses/index.ts

@@ -27,4 +27,5 @@ export * from "./sharpenPostProcess";
 export * from "./stereoscopicInterlacePostProcess";
 export * from "./tonemapPostProcess";
 export * from "./volumetricLightScatteringPostProcess";
-export * from "./vrDistortionCorrectionPostProcess";
+export * from "./vrDistortionCorrectionPostProcess";
+export * from "./vrMultiviewToSingleviewPostProcess";

+ 1 - 29
src/PostProcesses/vrDistortionCorrectionPostProcess.ts

@@ -6,7 +6,6 @@ import { Texture } from "../Materials/Textures/texture";
 import { PostProcess } from "./postProcess";
 
 import "../Shaders/vrDistortionCorrection.fragment";
-import "../Shaders/vrMultiviewToSingleview.fragment";
 
 /**
  * VRDistortionCorrectionPostProcess used for mobile VR
@@ -53,31 +52,4 @@ export class VRDistortionCorrectionPostProcess extends PostProcess {
             effect.setFloat4("HmdWarpParam", this._distortionFactors[0], this._distortionFactors[1], this._distortionFactors[2], this._distortionFactors[3]);
         });
     }
-}
-
-/**
- * VRMultiviewToSingleview used to convert multiview texture arrays to standard textures for scenarios such as webVR
- * This will not be used for webXR as it supports displaying texture arrays directly
- */
-export class VRMultiviewToSingleview extends PostProcess {
-    /**
-     * Initializes a VRMultiviewToSingleview
-     * @param name name of the post process
-     * @param camera camera to be applied to
-     * @param scaleFactor scaling factor to the size of the output texture
-     */
-    constructor(name: string, camera: Camera, scaleFactor: number) {
-        super(name, "vrMultiviewToSingleview", ["imageIndex"], ["multiviewSampler"], scaleFactor, camera, Texture.BILINEAR_SAMPLINGMODE);
-
-        this.onSizeChangedObservable.add(() => {
-        });
-        this.onApplyObservable.add((effect: Effect) => {
-            if (camera._scene.activeCamera && camera._scene.activeCamera.isLeftCamera) {
-                effect.setInt("imageIndex", 0);
-            }else {
-                effect.setInt("imageIndex", 1);
-            }
-            effect.setTexture("multiviewSampler", camera._multiviewTexture);
-        });
-    }
-}
+}

+ 34 - 0
src/PostProcesses/vrMultiviewToSingleviewPostProcess.ts

@@ -0,0 +1,34 @@
+import { Camera } from "../Cameras/camera";
+import { Effect } from "../Materials/effect";
+import { Texture } from "../Materials/Textures/texture";
+import { PostProcess } from "./postProcess";
+
+import "../Shaders/vrMultiviewToSingleview.fragment";
+import "../Engines/Extensions/engine.multiview";
+
+/**
+ * VRMultiviewToSingleview used to convert multiview texture arrays to standard textures for scenarios such as webVR
+ * This will not be used for webXR as it supports displaying texture arrays directly
+ */
+export class VRMultiviewToSingleviewPostProcess extends PostProcess {
+    /**
+     * Initializes a VRMultiviewToSingleview
+     * @param name name of the post process
+     * @param camera camera to be applied to
+     * @param scaleFactor scaling factor to the size of the output texture
+     */
+    constructor(name: string, camera: Camera, scaleFactor: number) {
+        super(name, "vrMultiviewToSingleview", ["imageIndex"], ["multiviewSampler"], scaleFactor, camera, Texture.BILINEAR_SAMPLINGMODE);
+
+        this.onSizeChangedObservable.add(() => {
+        });
+        this.onApplyObservable.add((effect: Effect) => {
+            if (camera._scene.activeCamera && camera._scene.activeCamera.isLeftCamera) {
+                effect.setInt("imageIndex", 0);
+            }else {
+                effect.setInt("imageIndex", 1);
+            }
+            effect.setTexture("multiviewSampler", camera._multiviewTexture);
+        });
+    }
+}

+ 3 - 1
src/assetContainer.ts

@@ -78,7 +78,9 @@ export class AssetContainer extends AbstractScene {
             this.scene.addReflectionProbe(o);
         });
 
-        this.scene.environmentTexture = this.environmentTexture;
+        if (this.environmentTexture) {
+            this.scene.environmentTexture = this.environmentTexture;
+        }
 
         for (let component of this.scene._serializableComponents) {
             component.addFromContainer(this);

+ 11 - 52
src/scene.ts

@@ -5,7 +5,7 @@ import { Observable, Observer } from "./Misc/observable";
 import { SmartArrayNoDuplicate, SmartArray, ISmartArrayLike } from "./Misc/smartArray";
 import { StringDictionary } from "./Misc/stringDictionary";
 import { Tags } from "./Misc/tags";
-import { Color4, Color3, Plane, Vector2, Vector3, Matrix, Tmp, Frustum } from "./Maths/math";
+import { Color4, Color3, Plane, Vector2, Vector3, Matrix, Frustum } from "./Maths/math";
 import { Geometry } from "./Meshes/geometry";
 import { TransformNode } from "./Meshes/transformNode";
 import { SubMesh } from "./Meshes/subMesh";
@@ -870,7 +870,8 @@ export class Scene extends AbstractScene implements IAnimatable {
     /** All of the active cameras added to this scene. */
     public activeCameras = new Array<Camera>();
 
-    private _activeCamera: Nullable<Camera>;
+    /** @hidden */
+    public _activeCamera: Nullable<Camera>;
     /** Gets or sets the current active camera */
     public get activeCamera(): Nullable<Camera> {
         return this._activeCamera;
@@ -1113,17 +1114,17 @@ export class Scene extends AbstractScene implements IAnimatable {
     public _activeAnimatables = new Array<Animatable>();
 
     private _transformMatrix = Matrix.Zero();
-    private _transformMatrixR = Matrix.Zero();
     private _sceneUbo: UniformBuffer;
-    private _multiviewSceneUbo: UniformBuffer;
 
-    private _viewMatrix: Matrix;
+    /** @hidden */
+    public _viewMatrix: Matrix;
     private _projectionMatrix: Matrix;
     private _wheelEventName = "";
     /** @hidden */
     public _forcedViewPosition: Nullable<Vector3>;
 
-    private _frustumPlanes: Plane[];
+    /** @hidden */
+    public _frustumPlanes: Plane[];
     /**
      * Gets the list of frustum planes (built from the active camera)
      */
@@ -1606,13 +1607,6 @@ export class Scene extends AbstractScene implements IAnimatable {
         this._sceneUbo.addUniform("view", 16);
     }
 
-    private _createMultiviewUbo(): void {
-        this._multiviewSceneUbo = new UniformBuffer(this._engine, undefined, true);
-        this._multiviewSceneUbo.addUniform("viewProjection", 16);
-        this._multiviewSceneUbo.addUniform("viewProjectionR", 16);
-        this._multiviewSceneUbo.addUniform("view", 16);
-    }
-
     // Pointers handling
     private _setRayOnPointerInfo(pointerInfo: PointerInfo) {
         if (pointerInfo.pickInfo && !pointerInfo.pickInfo._pickingUnavailable) {
@@ -2574,9 +2568,6 @@ export class Scene extends AbstractScene implements IAnimatable {
         this._projectionMatrix = projectionL;
 
         this._viewMatrix.multiplyToRef(this._projectionMatrix, this._transformMatrix);
-        if (viewR && projectionR) {
-            viewR.multiplyToRef(projectionR, this._transformMatrixR);
-        }
 
         // Update frustum
         if (!this._frustumPlanes) {
@@ -2585,16 +2576,8 @@ export class Scene extends AbstractScene implements IAnimatable {
             Frustum.GetPlanesToRef(this._transformMatrix, this._frustumPlanes);
         }
 
-        if (viewR && projectionR) {
-            viewR.multiplyToRef(projectionR, Tmp.Matrix[0]);
-            Frustum.GetRightPlaneToRef(Tmp.Matrix[0], this._frustumPlanes[3]); // Replace right plane by second camera right plane
-        }
-
         if (this._multiviewSceneUbo && this._multiviewSceneUbo.useUbo) {
-            this._multiviewSceneUbo.updateMatrix("viewProjection", this._transformMatrix);
-            this._multiviewSceneUbo.updateMatrix("viewProjectionR", this._transformMatrixR);
-            this._multiviewSceneUbo.updateMatrix("view", this._viewMatrix);
-            this._multiviewSceneUbo.update();
+            this._updateMultiviewUbo(viewR, projectionR);
         } else if (this._sceneUbo.useUbo) {
             this._sceneUbo.updateMatrix("viewProjection", this._transformMatrix);
             this._sceneUbo.updateMatrix("view", this._viewMatrix);
@@ -4045,7 +4028,8 @@ export class Scene extends AbstractScene implements IAnimatable {
     }
     /** @hidden */
     public _allowPostProcessClearColor = true;
-    private _renderForCamera(camera: Camera, rigParent?: Camera): void {
+    /** @hidden */
+    public _renderForCamera(camera: Camera, rigParent?: Camera): void {
         if (camera && camera._skipRendering) {
             return;
         }
@@ -4169,32 +4153,7 @@ export class Scene extends AbstractScene implements IAnimatable {
         }
 
         if (camera._useMultiviewToSingleView) {
-            // Multiview is only able to be displayed directly for API's such as webXR
-            // This displays a multiview image by rendering to the multiview image and then
-            // copying the result into the sub cameras instead of rendering them and proceeding as normal from there
-
-            // Render to a multiview texture
-            camera._resizeOrCreateMultiviewTexture(
-                (camera._rigPostProcess && camera._rigPostProcess && camera._rigPostProcess.width > 0) ? camera._rigPostProcess.width / 2 : this.getEngine().getRenderWidth(true) / 2,
-                (camera._rigPostProcess && camera._rigPostProcess && camera._rigPostProcess.height > 0) ? camera._rigPostProcess.height : this.getEngine().getRenderHeight(true)
-            );
-            if (!this._multiviewSceneUbo) {
-                this._createMultiviewUbo();
-            }
-            camera.outputRenderTarget = camera._multiviewTexture;
-            this._renderForCamera(camera);
-            camera.outputRenderTarget = null;
-
-            // Consume the multiview texture through a shader for each eye
-            for (var index = 0; index < camera._rigCameras.length; index++) {
-                var engine = this._engine;
-                this._activeCamera = camera._rigCameras[index];
-                engine.setViewport(this._activeCamera.viewport);
-                if (this.postProcessManager) {
-                    this.postProcessManager._prepareFrame();
-                    this.postProcessManager._finalizeFrame(this._activeCamera.isIntermediate);
-                }
-            }
+            this._renderMultiviewToSingleView(camera);
         } else {
             // rig cameras
             for (var index = 0; index < camera._rigCameras.length; index++) {