瀏覽代碼

Merge branch 'master' into fix-objserializer-handedness

Thibault Durand 5 年之前
父節點
當前提交
1648823f1f
共有 49 個文件被更改,包括 2710 次插入1849 次删除
  1. 241 218
      dist/preview release/babylon.d.ts
  2. 1 1
      dist/preview release/babylon.js
  3. 448 91
      dist/preview release/babylon.max.js
  4. 1 1
      dist/preview release/babylon.max.js.map
  5. 487 436
      dist/preview release/babylon.module.d.ts
  6. 243 218
      dist/preview release/documentation.d.ts
  7. 48 48
      dist/preview release/gui/babylon.gui.js
  8. 1 1
      dist/preview release/gui/babylon.gui.js.map
  9. 17 26
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  10. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js.map
  11. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  12. 17 26
      dist/preview release/loaders/babylon.glTFFileLoader.js
  13. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.js.map
  14. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  15. 2 0
      dist/preview release/loaders/babylonjs.loaders.d.ts
  16. 17 26
      dist/preview release/loaders/babylonjs.loaders.js
  17. 1 1
      dist/preview release/loaders/babylonjs.loaders.js.map
  18. 2 2
      dist/preview release/loaders/babylonjs.loaders.min.js
  19. 4 0
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  20. 1 1
      dist/preview release/packagesSizeBaseLine.json
  21. 487 436
      dist/preview release/viewer/babylon.module.d.ts
  22. 117 113
      dist/preview release/viewer/babylon.viewer.js
  23. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  24. 4 0
      dist/preview release/viewer/babylonjs.loaders.module.d.ts
  25. 6 0
      dist/preview release/what's new.md
  26. 6 1
      gui/src/2D/controls/textBlock.ts
  27. 3 2
      inspector/src/components/actionTabs/tabs/propertyGrids/animations/anchorSvgPoint.tsx
  28. 210 23
      inspector/src/components/actionTabs/tabs/propertyGrids/animations/animationCurveEditorComponent.tsx
  29. 21 1
      inspector/src/components/actionTabs/tabs/propertyGrids/animations/curveEditor.scss
  30. 9 1
      inspector/src/components/actionTabs/tabs/propertyGrids/animations/graphActionsBar.tsx
  31. 2 2
      inspector/src/components/actionTabs/tabs/propertyGrids/animations/keyframeSvgPoint.tsx
  32. 23 30
      loaders/src/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.ts
  33. 4 1
      loaders/src/glTF/2.0/glTFLoader.ts
  34. 2 2
      src/Layers/effectLayer.ts
  35. 6 11
      src/LibDeclarations/webxr.d.ts
  36. 6 4
      src/Lights/Shadows/shadowGenerator.ts
  37. 1 1
      src/Meshes/mesh.ts
  38. 18 0
      src/Meshes/subMesh.ts
  39. 7 0
      src/Meshes/thinInstanceMesh.ts
  40. 2 4
      src/PostProcesses/volumetricLightScatteringPostProcess.ts
  41. 2 4
      src/Rendering/depthRenderer.ts
  42. 2 4
      src/Rendering/geometryBufferRenderer.ts
  43. 167 90
      src/XR/features/WebXRAnchorSystem.ts
  44. 12 8
      src/XR/features/WebXRHitTest.ts
  45. 12 2
      src/XR/features/WebXRHitTestLegacy.ts
  46. 37 4
      src/XR/features/WebXRPlaneDetector.ts
  47. 1 1
      src/XR/webXRDefaultExperience.ts
  48. 3 0
      src/XR/webXRInputSource.ts
  49. 2 1
      tests/validation/config.json

+ 241 - 218
dist/preview release/babylon.d.ts

@@ -64999,6 +64999,10 @@ declare module BABYLON {
                 };
             };
         }
+    /**
+     * @hidden
+     */
+    export var _IDoNeedToBeInTheBuild2: number;
 }
 declare module BABYLON {
     /**
@@ -72088,6 +72092,15 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * An interface for all Hit test features
+     */
+    export interface IWebXRHitTestFeature<T extends IWebXRLegacyHitResult> extends IWebXRFeature {
+        /**
+         * Triggered when new babylon (transformed) hit test results are available
+         */
+        onHitTestResultObservable: Observable<T[]>;
+    }
+    /**
      * Options used for hit testing
      */
     export interface IWebXRLegacyHitTestOptions {
@@ -72118,7 +72131,7 @@ declare module BABYLON {
      * Hit test (or Ray-casting) is used to interact with the real world.
      * For further information read here - https://github.com/immersive-web/hit-test
      */
-    export class WebXRHitTestLegacy extends WebXRAbstractFeature {
+    export class WebXRHitTestLegacy extends WebXRAbstractFeature implements IWebXRHitTestFeature<IWebXRLegacyHitResult> {
         /**
          * options to use when constructing this feature
          */
@@ -72197,48 +72210,74 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Options used in the plane detector module
+     * Options used for hit testing (version 2)
      */
-    export interface IWebXRPlaneDetectorOptions {
+    export interface IWebXRHitTestOptions extends IWebXRLegacyHitTestOptions {
         /**
-         * The node to use to transform the local results to world coordinates
+         * Do not create a permanent hit test. Will usually be used when only
+         * transient inputs are needed.
          */
-        worldParentNode?: TransformNode;
+        disablePermanentHitTest?: boolean;
+        /**
+         * Enable transient (for example touch-based) hit test inspections
+         */
+        enableTransientHitTest?: boolean;
+        /**
+         * Offset ray for the permanent hit test
+         */
+        offsetRay?: Vector3;
+        /**
+         * Offset ray for the transient hit test
+         */
+        transientOffsetRay?: Vector3;
+        /**
+         * Instead of using viewer space for hit tests, use the reference space defined in the session manager
+         */
+        useReferenceSpace?: boolean;
     }
     /**
-     * A babylon interface for a WebXR plane.
-     * A Plane is actually a polygon, built from N points in space
-     *
-     * Supported in chrome 79, not supported in canary 81 ATM
+     * Interface defining the babylon result of hit-test
      */
-    export interface IWebXRPlane {
+    export interface IWebXRHitResult extends IWebXRLegacyHitResult {
         /**
-         * a babylon-assigned ID for this polygon
+         * The input source that generated this hit test (if transient)
          */
-        id: number;
+        inputSource?: XRInputSource;
         /**
-         * an array of vector3 points in babylon space. right/left hand system is taken into account.
+         * Is this a transient hit test
          */
-        polygonDefinition: Array<Vector3>;
+        isTransient?: boolean;
         /**
-         * A transformation matrix to apply on the mesh that will be built using the polygonDefinition
-         * Local vs. World are decided if worldParentNode was provided or not in the options when constructing the module
+         * Position of the hit test result
          */
-        transformationMatrix: Matrix;
+        position: Vector3;
         /**
-         * the native xr-plane object
+         * Rotation of the hit test result
          */
-        xrPlane: XRPlane;
+        rotationQuaternion: Quaternion;
+        /**
+         * The native hit test result
+         */
+        xrHitResult: XRHitTestResult;
     }
     /**
-     * The plane detector is used to detect planes in the real world when in AR
-     * For more information see https://github.com/immersive-web/real-world-geometry/
+     * The currently-working hit-test module.
+     * Hit test (or Ray-casting) is used to interact with the real world.
+     * For further information read here - https://github.com/immersive-web/hit-test
+     *
+     * Tested on chrome (mobile) 80.
      */
-    export class WebXRPlaneDetector extends WebXRAbstractFeature {
-        private _options;
-        private _detectedPlanes;
-        private _enabled;
-        private _lastFrameDetected;
+    export class WebXRHitTest extends WebXRAbstractFeature implements IWebXRHitTestFeature<IWebXRHitResult> {
+        /**
+         * options to use when constructing this feature
+         */
+        readonly options: IWebXRHitTestOptions;
+        private _tmpMat;
+        private _tmpPos;
+        private _tmpQuat;
+        private _transientXrHitTestSource;
+        private _xrHitTestSource;
+        private initHitTestSource;
         /**
          * The module's name
          */
@@ -72250,36 +72289,49 @@ declare module BABYLON {
          */
         static readonly Version: number;
         /**
-         * Observers registered here will be executed when a new plane was added to the session
+         * When set to true, each hit test will have its own position/rotation objects
+         * When set to false, position and rotation objects will be reused for each hit test. It is expected that
+         * the developers will clone them or copy them as they see fit.
          */
-        onPlaneAddedObservable: Observable<IWebXRPlane>;
+        autoCloneTransformation: boolean;
         /**
-         * Observers registered here will be executed when a plane is no longer detected in the session
+         * Triggered when new babylon (transformed) hit test results are available
          */
-        onPlaneRemovedObservable: Observable<IWebXRPlane>;
+        onHitTestResultObservable: Observable<IWebXRHitResult[]>;
         /**
-         * Observers registered here will be executed when an existing plane updates (for example - expanded)
-         * This can execute N times every frame
+         * Use this to temporarily pause hit test checks.
          */
-        onPlaneUpdatedObservable: Observable<IWebXRPlane>;
+        paused: boolean;
         /**
-         * construct a new Plane Detector
-         * @param _xrSessionManager an instance of xr Session manager
-         * @param _options configuration to use when constructing this feature
+         * Creates a new instance of the hit test feature
+         * @param _xrSessionManager an instance of WebXRSessionManager
+         * @param options options to use when constructing this feature
          */
-        constructor(_xrSessionManager: WebXRSessionManager, _options?: IWebXRPlaneDetectorOptions);
+        constructor(_xrSessionManager: WebXRSessionManager, 
+        /**
+         * options to use when constructing this feature
+         */
+        options?: IWebXRHitTestOptions);
+        /**
+         * attach this feature
+         * Will usually be called by the features manager
+         *
+         * @returns true if successful.
+         */
+        attach(): boolean;
+        /**
+         * detach this feature.
+         * Will usually be called by the features manager
+         *
+         * @returns true if successful.
+         */
+        detach(): boolean;
         /**
          * Dispose this feature and all of the resources attached
          */
         dispose(): void;
         protected _onXRFrame(frame: XRFrame): void;
-        private _init;
-        private _updatePlaneWithXRPlane;
-        /**
-         * avoiding using Array.find for global support.
-         * @param xrPlane the plane to find in the array
-         */
-        private findIndexInPlaneArray;
+        private _processWebXRHitTestResult;
     }
 }
 declare module BABYLON {
@@ -72288,18 +72340,14 @@ declare module BABYLON {
      */
     export interface IWebXRAnchorSystemOptions {
         /**
-         * Should a new anchor be added every time a select event is triggered
-         */
-        addAnchorOnSelect?: boolean;
-        /**
-         * should the anchor system use plane detection.
-         * If set to true, the plane-detection feature should be set using setPlaneDetector
-         */
-        usePlaneDetection?: boolean;
-        /**
          * a node that will be used to convert local to world coordinates
          */
         worldParentNode?: TransformNode;
+        /**
+         * If set to true a reference of the created anchors will be kept until the next session starts
+         * If not defined, anchors will be removed from the array when the feature is detached or the session ended.
+         */
+        doNotRemoveAnchorsOnSessionEnded?: boolean;
     }
     /**
      * A babylon container for an XR Anchor
@@ -72317,21 +72365,21 @@ declare module BABYLON {
          * The native anchor object
          */
         xrAnchor: XRAnchor;
+        /**
+         * if defined, this object will be constantly updated by the anchor's position and rotation
+         */
+        attachedNode?: TransformNode;
     }
     /**
-     * An implementation of the anchor system of WebXR.
-     * Note that the current documented implementation is not available in any browser. Future implementations
-     * will use the frame to create an anchor and not the session or a detected plane
+     * An implementation of the anchor system for WebXR.
      * For further information see https://github.com/immersive-web/anchors/
      */
     export class WebXRAnchorSystem extends WebXRAbstractFeature {
         private _options;
-        private _enabled;
-        private _hitTestModule;
         private _lastFrameDetected;
-        private _onSelect;
-        private _planeDetector;
         private _trackedAnchors;
+        private _referenceSpaceForFrameAnchors;
+        private _futureAnchors;
         /**
          * The module's name
          */
@@ -72356,26 +72404,43 @@ declare module BABYLON {
          */
         onAnchorUpdatedObservable: Observable<IWebXRAnchor>;
         /**
+         * Set the reference space to use for anchor creation, when not using a hit test.
+         * Will default to the session's reference space if not defined
+         */
+        set referenceSpaceForFrameAnchors(referenceSpace: XRReferenceSpace);
+        /**
          * constructs a new anchor system
          * @param _xrSessionManager an instance of WebXRSessionManager
          * @param _options configuration object for this feature
          */
         constructor(_xrSessionManager: WebXRSessionManager, _options?: IWebXRAnchorSystemOptions);
+        private _tmpVector;
+        private _tmpQuaternion;
+        private _populateTmpTransformation;
         /**
-         * Add anchor at a specific XR point.
+         * Create a new anchor point using a hit test result at a specific point in the scene
+         * An anchor is tracked only after it is added to the trackerAnchors in xrFrame. The promise returned here does not yet guaranty that.
+         * Use onAnchorAddedObservable to get newly added anchors if you require tracking guaranty.
          *
-         * @param xrRigidTransformation xr-coordinates where a new anchor should be added
-         * @param anchorCreator the object o use to create an anchor with. either a session or a plane
-         * @returns a promise the fulfills when the anchor was created
-         */
-        addAnchorAtRigidTransformation(xrRigidTransformation: XRRigidTransform, anchorCreator?: XRAnchorCreator): Promise<XRAnchor>;
-        /**
-         * attach this feature
-         * Will usually be called by the features manager
+         * @param hitTestResult The hit test result to use for this anchor creation
+         * @param position an optional position offset for this anchor
+         * @param rotationQuaternion an optional rotation offset for this anchor
+         * @returns A promise that fulfills when the XR anchor was registered in the system (but not necessarily added to the tracked anchors)
+         */
+        addAnchorPointUsingHitTestResultAsync(hitTestResult: IWebXRHitResult, position?: Vector3, rotationQuaternion?: Quaternion): Promise<XRAnchor>;
+        /**
+         * Add a new anchor at a specific position and rotation
+         * This function will add a new anchor per default in the next available frame. Unless forced, the createAnchor function
+         * will be called in the next xrFrame loop to make sure that the anchor can be created correctly.
+         * An anchor is tracked only after it is added to the trackerAnchors in xrFrame. The promise returned here does not yet guaranty that.
+         * Use onAnchorAddedObservable to get newly added anchors if you require tracking guaranty.
          *
-         * @returns true if successful.
+         * @param position the position in which to add an anchor
+         * @param rotationQuaternion an optional rotation for the anchor transformation
+         * @param forceCreateInCurrentFrame force the creation of this anchor in the current frame. Must be called inside xrFrame loop!
+         * @returns A promise that fulfills when the XR anchor was registered in the system (but not necessarily added to the tracked anchors)
          */
-        attach(): boolean;
+        addAnchorAtPositionAndRotationAsync(position: Vector3, rotationQuaternion?: Quaternion, forceCreateInCurrentFrame?: boolean): Promise<XRAnchor>;
         /**
          * detach this feature.
          * Will usually be called by the features manager
@@ -72387,24 +72452,113 @@ declare module BABYLON {
          * Dispose this feature and all of the resources attached
          */
         dispose(): void;
+        protected _onXRFrame(frame: XRFrame): void;
+        /**
+         * avoiding using Array.find for global support.
+         * @param xrAnchor the plane to find in the array
+         */
+        private _findIndexInAnchorArray;
+        private _updateAnchorWithXRFrame;
+        private _createAnchorAtTransformation;
+    }
+}
+declare module BABYLON {
+    /**
+     * Options used in the plane detector module
+     */
+    export interface IWebXRPlaneDetectorOptions {
+        /**
+         * The node to use to transform the local results to world coordinates
+         */
+        worldParentNode?: TransformNode;
+        /**
+         * If set to true a reference of the created planes will be kept until the next session starts
+         * If not defined, planes will be removed from the array when the feature is detached or the session ended.
+         */
+        doNotRemovePlanesOnSessionEnded?: boolean;
+    }
+    /**
+     * A babylon interface for a WebXR plane.
+     * A Plane is actually a polygon, built from N points in space
+     *
+     * Supported in chrome 79, not supported in canary 81 ATM
+     */
+    export interface IWebXRPlane {
+        /**
+         * a babylon-assigned ID for this polygon
+         */
+        id: number;
+        /**
+         * an array of vector3 points in babylon space. right/left hand system is taken into account.
+         */
+        polygonDefinition: Array<Vector3>;
+        /**
+         * A transformation matrix to apply on the mesh that will be built using the polygonDefinition
+         * Local vs. World are decided if worldParentNode was provided or not in the options when constructing the module
+         */
+        transformationMatrix: Matrix;
+        /**
+         * the native xr-plane object
+         */
+        xrPlane: XRPlane;
+    }
+    /**
+     * The plane detector is used to detect planes in the real world when in AR
+     * For more information see https://github.com/immersive-web/real-world-geometry/
+     */
+    export class WebXRPlaneDetector extends WebXRAbstractFeature {
+        private _options;
+        private _detectedPlanes;
+        private _enabled;
+        private _lastFrameDetected;
+        /**
+         * The module's name
+         */
+        static readonly Name: string;
+        /**
+         * The (Babylon) version of this module.
+         * This is an integer representing the implementation version.
+         * This number does not correspond to the WebXR specs version
+         */
+        static readonly Version: number;
+        /**
+         * Observers registered here will be executed when a new plane was added to the session
+         */
+        onPlaneAddedObservable: Observable<IWebXRPlane>;
+        /**
+         * Observers registered here will be executed when a plane is no longer detected in the session
+         */
+        onPlaneRemovedObservable: Observable<IWebXRPlane>;
         /**
-         * If set, it will improve performance by using the current hit-test results instead of executing a new hit-test
-         * @param hitTestModule the hit-test module to use.
+         * Observers registered here will be executed when an existing plane updates (for example - expanded)
+         * This can execute N times every frame
          */
-        setHitTestModule(hitTestModule: WebXRHitTestLegacy): void;
+        onPlaneUpdatedObservable: Observable<IWebXRPlane>;
         /**
-         * set the plane detector to use in order to create anchors from frames
-         * @param planeDetector the plane-detector module to use
-         * @param enable enable plane-anchors. default is true
+         * construct a new Plane Detector
+         * @param _xrSessionManager an instance of xr Session manager
+         * @param _options configuration to use when constructing this feature
          */
-        setPlaneDetector(planeDetector: WebXRPlaneDetector, enable?: boolean): void;
+        constructor(_xrSessionManager: WebXRSessionManager, _options?: IWebXRPlaneDetectorOptions);
+        /**
+         * detach this feature.
+         * Will usually be called by the features manager
+         *
+         * @returns true if successful.
+         */
+        detach(): boolean;
+        /**
+         * Dispose this feature and all of the resources attached
+         */
+        dispose(): void;
         protected _onXRFrame(frame: XRFrame): void;
+        private _init;
+        private _updatePlaneWithXRPlane;
         /**
          * avoiding using Array.find for global support.
-         * @param xrAnchor the plane to find in the array
+         * @param xrPlane the plane to find in the array
          */
-        private _findIndexInAnchorArray;
-        private _updateAnchorWithXRFrame;
+        private findIndexInPlaneArray;
     }
 }
 declare module BABYLON {
@@ -72645,132 +72799,6 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Options used for hit testing (version 2)
-     */
-    export interface IWebXRHitTestOptions extends IWebXRLegacyHitTestOptions {
-        /**
-         * Do not create a permanent hit test. Will usually be used when only
-         * transient inputs are needed.
-         */
-        disablePermanentHitTest?: boolean;
-        /**
-         * Enable transient (for example touch-based) hit test inspections
-         */
-        enableTransientHitTest?: boolean;
-        /**
-         * Offset ray for the permanent hit test
-         */
-        offsetRay?: Vector3;
-        /**
-         * Offset ray for the transient hit test
-         */
-        transientOffsetRay?: Vector3;
-        /**
-         * Instead of using viewer space for hit tests, use the reference space defined in the session manager
-         */
-        useReferenceSpace?: boolean;
-    }
-    /**
-     * Interface defining the babylon result of hit-test
-     */
-    export interface IWebXRHitResult extends IWebXRLegacyHitResult {
-        /**
-         * The input source that generated this hit test (if transient)
-         */
-        inputSource?: XRInputSource;
-        /**
-         * Is this a transient hit test
-         */
-        isTransient?: boolean;
-        /**
-         * Position of the hit test result
-         */
-        position: Vector3;
-        /**
-         * Rotation of the hit test result
-         */
-        rotationQuaternion: Quaternion;
-    }
-    /**
-     * The currently-working hit-test module.
-     * Hit test (or Ray-casting) is used to interact with the real world.
-     * For further information read here - https://github.com/immersive-web/hit-test
-     *
-     * Tested on chrome (mobile) 80.
-     */
-    export class WebXRHitTest extends WebXRAbstractFeature {
-        /**
-         * options to use when constructing this feature
-         */
-        readonly options: IWebXRHitTestOptions;
-        private _tmpMat;
-        private _tmpPos;
-        private _tmpQuat;
-        private _transientXrHitTestSource;
-        private _xrHitTestSource;
-        private initHitTestSource;
-        /**
-         * The module's name
-         */
-        static readonly Name: string;
-        /**
-         * The (Babylon) version of this module.
-         * This is an integer representing the implementation version.
-         * This number does not correspond to the WebXR specs version
-         */
-        static readonly Version: number;
-        /**
-         * When set to true, each hit test will have its own position/rotation objects
-         * When set to false, position and rotation objects will be reused for each hit test. It is expected that
-         * the developers will clone them or copy them as they see fit.
-         */
-        autoCloneTransformation: boolean;
-        /**
-         * Populated with the last native XR Hit Results
-         */
-        lastNativeXRHitResults: XRHitResult[];
-        /**
-         * Triggered when new babylon (transformed) hit test results are available
-         */
-        onHitTestResultObservable: Observable<IWebXRHitResult[]>;
-        /**
-         * Use this to temporarily pause hit test checks.
-         */
-        paused: boolean;
-        /**
-         * Creates a new instance of the hit test feature
-         * @param _xrSessionManager an instance of WebXRSessionManager
-         * @param options options to use when constructing this feature
-         */
-        constructor(_xrSessionManager: WebXRSessionManager, 
-        /**
-         * options to use when constructing this feature
-         */
-        options?: IWebXRHitTestOptions);
-        /**
-         * attach this feature
-         * Will usually be called by the features manager
-         *
-         * @returns true if successful.
-         */
-        attach(): boolean;
-        /**
-         * detach this feature.
-         * Will usually be called by the features manager
-         *
-         * @returns true if successful.
-         */
-        detach(): boolean;
-        /**
-         * Dispose this feature and all of the resources attached
-         */
-        dispose(): void;
-        protected _onXRFrame(frame: XRFrame): void;
-        private _processWebXRHitTestResult;
-    }
-}
-declare module BABYLON {
-    /**
      * The motion controller class for all microsoft mixed reality controllers
      */
     export class WebXRMicrosoftMixedRealityController extends WebXRAbstractMotionController {
@@ -73574,7 +73602,7 @@ interface XRSessionInit {
     requiredFeatures?: string[];
 }
 
-interface XRSession extends XRAnchorCreator {
+interface XRSession {
     addEventListener: Function;
     removeEventListener: Function;
     requestReferenceSpace(type: XRReferenceSpaceType): Promise<XRReferenceSpace>;
@@ -73615,6 +73643,7 @@ interface XRFrame {
     getHitTestResultsForTransientInput(hitTestSource: XRTransientInputHitTestSource): Array<XRTransientInputHitTestResult>;
     // Anchors
     trackedAnchors?: XRAnchorSet;
+    createAnchor(pose: XRRigidTransform, space: XRSpace): Promise<XRAnchor>;
     // Planes
     worldInformation: {
         detectedPlanes?: XRPlaneSet;
@@ -73699,6 +73728,8 @@ interface XRTransientInputHitTestResult {
 
 interface XRHitTestResult {
     getPose(baseSpace: XRSpace): XRPose | undefined;
+    // When anchor system is enabled
+    createAnchor?(pose: XRRigidTransform): Promise<XRAnchor>;
 }
 
 interface XRHitTestSource {
@@ -73722,21 +73753,13 @@ interface XRTransientInputHitTestOptionsInit {
 }
 
 interface XRAnchor {
-    // remove?
-    id?: string;
     anchorSpace: XRSpace;
-    lastChangedTime: number;
-    detach(): void;
+    delete(): void;
 }
 
-interface XRPlane extends XRAnchorCreator {
+interface XRPlane {
     orientation: "Horizontal" | "Vertical";
     planeSpace: XRSpace;
     polygon: Array<DOMPointReadOnly>;
     lastChangedTime: number;
-}
-
-interface XRAnchorCreator {
-    // AR Anchors
-    createAnchor(pose: XRPose | XRRigidTransform, referenceSpace: XRReferenceSpace): Promise<XRAnchor>;
 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.js


File diff suppressed because it is too large
+ 448 - 91
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.max.js.map


File diff suppressed because it is too large
+ 487 - 436
dist/preview release/babylon.module.d.ts


+ 243 - 218
dist/preview release/documentation.d.ts

@@ -64999,6 +64999,10 @@ declare module BABYLON {
                 };
             };
         }
+    /**
+     * @hidden
+     */
+    export var _IDoNeedToBeInTheBuild2: number;
 }
 declare module BABYLON {
     /**
@@ -72088,6 +72092,15 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * An interface for all Hit test features
+     */
+    export interface IWebXRHitTestFeature<T extends IWebXRLegacyHitResult> extends IWebXRFeature {
+        /**
+         * Triggered when new babylon (transformed) hit test results are available
+         */
+        onHitTestResultObservable: Observable<T[]>;
+    }
+    /**
      * Options used for hit testing
      */
     export interface IWebXRLegacyHitTestOptions {
@@ -72118,7 +72131,7 @@ declare module BABYLON {
      * Hit test (or Ray-casting) is used to interact with the real world.
      * For further information read here - https://github.com/immersive-web/hit-test
      */
-    export class WebXRHitTestLegacy extends WebXRAbstractFeature {
+    export class WebXRHitTestLegacy extends WebXRAbstractFeature implements IWebXRHitTestFeature<IWebXRLegacyHitResult> {
         /**
          * options to use when constructing this feature
          */
@@ -72197,48 +72210,74 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Options used in the plane detector module
+     * Options used for hit testing (version 2)
      */
-    export interface IWebXRPlaneDetectorOptions {
+    export interface IWebXRHitTestOptions extends IWebXRLegacyHitTestOptions {
         /**
-         * The node to use to transform the local results to world coordinates
+         * Do not create a permanent hit test. Will usually be used when only
+         * transient inputs are needed.
          */
-        worldParentNode?: TransformNode;
+        disablePermanentHitTest?: boolean;
+        /**
+         * Enable transient (for example touch-based) hit test inspections
+         */
+        enableTransientHitTest?: boolean;
+        /**
+         * Offset ray for the permanent hit test
+         */
+        offsetRay?: Vector3;
+        /**
+         * Offset ray for the transient hit test
+         */
+        transientOffsetRay?: Vector3;
+        /**
+         * Instead of using viewer space for hit tests, use the reference space defined in the session manager
+         */
+        useReferenceSpace?: boolean;
     }
     /**
-     * A babylon interface for a WebXR plane.
-     * A Plane is actually a polygon, built from N points in space
-     *
-     * Supported in chrome 79, not supported in canary 81 ATM
+     * Interface defining the babylon result of hit-test
      */
-    export interface IWebXRPlane {
+    export interface IWebXRHitResult extends IWebXRLegacyHitResult {
         /**
-         * a babylon-assigned ID for this polygon
+         * The input source that generated this hit test (if transient)
          */
-        id: number;
+        inputSource?: XRInputSource;
         /**
-         * an array of vector3 points in babylon space. right/left hand system is taken into account.
+         * Is this a transient hit test
          */
-        polygonDefinition: Array<Vector3>;
+        isTransient?: boolean;
         /**
-         * A transformation matrix to apply on the mesh that will be built using the polygonDefinition
-         * Local vs. World are decided if worldParentNode was provided or not in the options when constructing the module
+         * Position of the hit test result
          */
-        transformationMatrix: Matrix;
+        position: Vector3;
         /**
-         * the native xr-plane object
+         * Rotation of the hit test result
          */
-        xrPlane: XRPlane;
+        rotationQuaternion: Quaternion;
+        /**
+         * The native hit test result
+         */
+        xrHitResult: XRHitTestResult;
     }
     /**
-     * The plane detector is used to detect planes in the real world when in AR
-     * For more information see https://github.com/immersive-web/real-world-geometry/
+     * The currently-working hit-test module.
+     * Hit test (or Ray-casting) is used to interact with the real world.
+     * For further information read here - https://github.com/immersive-web/hit-test
+     *
+     * Tested on chrome (mobile) 80.
      */
-    export class WebXRPlaneDetector extends WebXRAbstractFeature {
-        private _options;
-        private _detectedPlanes;
-        private _enabled;
-        private _lastFrameDetected;
+    export class WebXRHitTest extends WebXRAbstractFeature implements IWebXRHitTestFeature<IWebXRHitResult> {
+        /**
+         * options to use when constructing this feature
+         */
+        readonly options: IWebXRHitTestOptions;
+        private _tmpMat;
+        private _tmpPos;
+        private _tmpQuat;
+        private _transientXrHitTestSource;
+        private _xrHitTestSource;
+        private initHitTestSource;
         /**
          * The module's name
          */
@@ -72250,36 +72289,49 @@ declare module BABYLON {
          */
         static readonly Version: number;
         /**
-         * Observers registered here will be executed when a new plane was added to the session
+         * When set to true, each hit test will have its own position/rotation objects
+         * When set to false, position and rotation objects will be reused for each hit test. It is expected that
+         * the developers will clone them or copy them as they see fit.
          */
-        onPlaneAddedObservable: Observable<IWebXRPlane>;
+        autoCloneTransformation: boolean;
         /**
-         * Observers registered here will be executed when a plane is no longer detected in the session
+         * Triggered when new babylon (transformed) hit test results are available
          */
-        onPlaneRemovedObservable: Observable<IWebXRPlane>;
+        onHitTestResultObservable: Observable<IWebXRHitResult[]>;
         /**
-         * Observers registered here will be executed when an existing plane updates (for example - expanded)
-         * This can execute N times every frame
+         * Use this to temporarily pause hit test checks.
          */
-        onPlaneUpdatedObservable: Observable<IWebXRPlane>;
+        paused: boolean;
         /**
-         * construct a new Plane Detector
-         * @param _xrSessionManager an instance of xr Session manager
-         * @param _options configuration to use when constructing this feature
+         * Creates a new instance of the hit test feature
+         * @param _xrSessionManager an instance of WebXRSessionManager
+         * @param options options to use when constructing this feature
          */
-        constructor(_xrSessionManager: WebXRSessionManager, _options?: IWebXRPlaneDetectorOptions);
+        constructor(_xrSessionManager: WebXRSessionManager, 
+        /**
+         * options to use when constructing this feature
+         */
+        options?: IWebXRHitTestOptions);
+        /**
+         * attach this feature
+         * Will usually be called by the features manager
+         *
+         * @returns true if successful.
+         */
+        attach(): boolean;
+        /**
+         * detach this feature.
+         * Will usually be called by the features manager
+         *
+         * @returns true if successful.
+         */
+        detach(): boolean;
         /**
          * Dispose this feature and all of the resources attached
          */
         dispose(): void;
         protected _onXRFrame(frame: XRFrame): void;
-        private _init;
-        private _updatePlaneWithXRPlane;
-        /**
-         * avoiding using Array.find for global support.
-         * @param xrPlane the plane to find in the array
-         */
-        private findIndexInPlaneArray;
+        private _processWebXRHitTestResult;
     }
 }
 declare module BABYLON {
@@ -72288,18 +72340,14 @@ declare module BABYLON {
      */
     export interface IWebXRAnchorSystemOptions {
         /**
-         * Should a new anchor be added every time a select event is triggered
-         */
-        addAnchorOnSelect?: boolean;
-        /**
-         * should the anchor system use plane detection.
-         * If set to true, the plane-detection feature should be set using setPlaneDetector
-         */
-        usePlaneDetection?: boolean;
-        /**
          * a node that will be used to convert local to world coordinates
          */
         worldParentNode?: TransformNode;
+        /**
+         * If set to true a reference of the created anchors will be kept until the next session starts
+         * If not defined, anchors will be removed from the array when the feature is detached or the session ended.
+         */
+        doNotRemoveAnchorsOnSessionEnded?: boolean;
     }
     /**
      * A babylon container for an XR Anchor
@@ -72317,21 +72365,21 @@ declare module BABYLON {
          * The native anchor object
          */
         xrAnchor: XRAnchor;
+        /**
+         * if defined, this object will be constantly updated by the anchor's position and rotation
+         */
+        attachedNode?: TransformNode;
     }
     /**
-     * An implementation of the anchor system of WebXR.
-     * Note that the current documented implementation is not available in any browser. Future implementations
-     * will use the frame to create an anchor and not the session or a detected plane
+     * An implementation of the anchor system for WebXR.
      * For further information see https://github.com/immersive-web/anchors/
      */
     export class WebXRAnchorSystem extends WebXRAbstractFeature {
         private _options;
-        private _enabled;
-        private _hitTestModule;
         private _lastFrameDetected;
-        private _onSelect;
-        private _planeDetector;
         private _trackedAnchors;
+        private _referenceSpaceForFrameAnchors;
+        private _futureAnchors;
         /**
          * The module's name
          */
@@ -72356,26 +72404,43 @@ declare module BABYLON {
          */
         onAnchorUpdatedObservable: Observable<IWebXRAnchor>;
         /**
+         * Set the reference space to use for anchor creation, when not using a hit test.
+         * Will default to the session's reference space if not defined
+         */
+        set referenceSpaceForFrameAnchors(referenceSpace: XRReferenceSpace);
+        /**
          * constructs a new anchor system
          * @param _xrSessionManager an instance of WebXRSessionManager
          * @param _options configuration object for this feature
          */
         constructor(_xrSessionManager: WebXRSessionManager, _options?: IWebXRAnchorSystemOptions);
+        private _tmpVector;
+        private _tmpQuaternion;
+        private _populateTmpTransformation;
         /**
-         * Add anchor at a specific XR point.
+         * Create a new anchor point using a hit test result at a specific point in the scene
+         * An anchor is tracked only after it is added to the trackerAnchors in xrFrame. The promise returned here does not yet guaranty that.
+         * Use onAnchorAddedObservable to get newly added anchors if you require tracking guaranty.
          *
-         * @param xrRigidTransformation xr-coordinates where a new anchor should be added
-         * @param anchorCreator the object o use to create an anchor with. either a session or a plane
-         * @returns a promise the fulfills when the anchor was created
-         */
-        addAnchorAtRigidTransformation(xrRigidTransformation: XRRigidTransform, anchorCreator?: XRAnchorCreator): Promise<XRAnchor>;
-        /**
-         * attach this feature
-         * Will usually be called by the features manager
+         * @param hitTestResult The hit test result to use for this anchor creation
+         * @param position an optional position offset for this anchor
+         * @param rotationQuaternion an optional rotation offset for this anchor
+         * @returns A promise that fulfills when the XR anchor was registered in the system (but not necessarily added to the tracked anchors)
+         */
+        addAnchorPointUsingHitTestResultAsync(hitTestResult: IWebXRHitResult, position?: Vector3, rotationQuaternion?: Quaternion): Promise<XRAnchor>;
+        /**
+         * Add a new anchor at a specific position and rotation
+         * This function will add a new anchor per default in the next available frame. Unless forced, the createAnchor function
+         * will be called in the next xrFrame loop to make sure that the anchor can be created correctly.
+         * An anchor is tracked only after it is added to the trackerAnchors in xrFrame. The promise returned here does not yet guaranty that.
+         * Use onAnchorAddedObservable to get newly added anchors if you require tracking guaranty.
          *
-         * @returns true if successful.
+         * @param position the position in which to add an anchor
+         * @param rotationQuaternion an optional rotation for the anchor transformation
+         * @param forceCreateInCurrentFrame force the creation of this anchor in the current frame. Must be called inside xrFrame loop!
+         * @returns A promise that fulfills when the XR anchor was registered in the system (but not necessarily added to the tracked anchors)
          */
-        attach(): boolean;
+        addAnchorAtPositionAndRotationAsync(position: Vector3, rotationQuaternion?: Quaternion, forceCreateInCurrentFrame?: boolean): Promise<XRAnchor>;
         /**
          * detach this feature.
          * Will usually be called by the features manager
@@ -72387,24 +72452,113 @@ declare module BABYLON {
          * Dispose this feature and all of the resources attached
          */
         dispose(): void;
+        protected _onXRFrame(frame: XRFrame): void;
         /**
-         * If set, it will improve performance by using the current hit-test results instead of executing a new hit-test
-         * @param hitTestModule the hit-test module to use.
+         * avoiding using Array.find for global support.
+         * @param xrAnchor the plane to find in the array
          */
-        setHitTestModule(hitTestModule: WebXRHitTestLegacy): void;
+        private _findIndexInAnchorArray;
+        private _updateAnchorWithXRFrame;
+        private _createAnchorAtTransformation;
+    }
+}
+declare module BABYLON {
+    /**
+     * Options used in the plane detector module
+     */
+    export interface IWebXRPlaneDetectorOptions {
         /**
-         * set the plane detector to use in order to create anchors from frames
-         * @param planeDetector the plane-detector module to use
-         * @param enable enable plane-anchors. default is true
+         * The node to use to transform the local results to world coordinates
          */
-        setPlaneDetector(planeDetector: WebXRPlaneDetector, enable?: boolean): void;
+        worldParentNode?: TransformNode;
+        /**
+         * If set to true a reference of the created planes will be kept until the next session starts
+         * If not defined, planes will be removed from the array when the feature is detached or the session ended.
+         */
+        doNotRemovePlanesOnSessionEnded?: boolean;
+    }
+    /**
+     * A babylon interface for a WebXR plane.
+     * A Plane is actually a polygon, built from N points in space
+     *
+     * Supported in chrome 79, not supported in canary 81 ATM
+     */
+    export interface IWebXRPlane {
+        /**
+         * a babylon-assigned ID for this polygon
+         */
+        id: number;
+        /**
+         * an array of vector3 points in babylon space. right/left hand system is taken into account.
+         */
+        polygonDefinition: Array<Vector3>;
+        /**
+         * A transformation matrix to apply on the mesh that will be built using the polygonDefinition
+         * Local vs. World are decided if worldParentNode was provided or not in the options when constructing the module
+         */
+        transformationMatrix: Matrix;
+        /**
+         * the native xr-plane object
+         */
+        xrPlane: XRPlane;
+    }
+    /**
+     * The plane detector is used to detect planes in the real world when in AR
+     * For more information see https://github.com/immersive-web/real-world-geometry/
+     */
+    export class WebXRPlaneDetector extends WebXRAbstractFeature {
+        private _options;
+        private _detectedPlanes;
+        private _enabled;
+        private _lastFrameDetected;
+        /**
+         * The module's name
+         */
+        static readonly Name: string;
+        /**
+         * The (Babylon) version of this module.
+         * This is an integer representing the implementation version.
+         * This number does not correspond to the WebXR specs version
+         */
+        static readonly Version: number;
+        /**
+         * Observers registered here will be executed when a new plane was added to the session
+         */
+        onPlaneAddedObservable: Observable<IWebXRPlane>;
+        /**
+         * Observers registered here will be executed when a plane is no longer detected in the session
+         */
+        onPlaneRemovedObservable: Observable<IWebXRPlane>;
+        /**
+         * Observers registered here will be executed when an existing plane updates (for example - expanded)
+         * This can execute N times every frame
+         */
+        onPlaneUpdatedObservable: Observable<IWebXRPlane>;
+        /**
+         * construct a new Plane Detector
+         * @param _xrSessionManager an instance of xr Session manager
+         * @param _options configuration to use when constructing this feature
+         */
+        constructor(_xrSessionManager: WebXRSessionManager, _options?: IWebXRPlaneDetectorOptions);
+        /**
+         * detach this feature.
+         * Will usually be called by the features manager
+         *
+         * @returns true if successful.
+         */
+        detach(): boolean;
+        /**
+         * Dispose this feature and all of the resources attached
+         */
+        dispose(): void;
         protected _onXRFrame(frame: XRFrame): void;
+        private _init;
+        private _updatePlaneWithXRPlane;
         /**
          * avoiding using Array.find for global support.
-         * @param xrAnchor the plane to find in the array
+         * @param xrPlane the plane to find in the array
          */
-        private _findIndexInAnchorArray;
-        private _updateAnchorWithXRFrame;
+        private findIndexInPlaneArray;
     }
 }
 declare module BABYLON {
@@ -72645,132 +72799,6 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Options used for hit testing (version 2)
-     */
-    export interface IWebXRHitTestOptions extends IWebXRLegacyHitTestOptions {
-        /**
-         * Do not create a permanent hit test. Will usually be used when only
-         * transient inputs are needed.
-         */
-        disablePermanentHitTest?: boolean;
-        /**
-         * Enable transient (for example touch-based) hit test inspections
-         */
-        enableTransientHitTest?: boolean;
-        /**
-         * Offset ray for the permanent hit test
-         */
-        offsetRay?: Vector3;
-        /**
-         * Offset ray for the transient hit test
-         */
-        transientOffsetRay?: Vector3;
-        /**
-         * Instead of using viewer space for hit tests, use the reference space defined in the session manager
-         */
-        useReferenceSpace?: boolean;
-    }
-    /**
-     * Interface defining the babylon result of hit-test
-     */
-    export interface IWebXRHitResult extends IWebXRLegacyHitResult {
-        /**
-         * The input source that generated this hit test (if transient)
-         */
-        inputSource?: XRInputSource;
-        /**
-         * Is this a transient hit test
-         */
-        isTransient?: boolean;
-        /**
-         * Position of the hit test result
-         */
-        position: Vector3;
-        /**
-         * Rotation of the hit test result
-         */
-        rotationQuaternion: Quaternion;
-    }
-    /**
-     * The currently-working hit-test module.
-     * Hit test (or Ray-casting) is used to interact with the real world.
-     * For further information read here - https://github.com/immersive-web/hit-test
-     *
-     * Tested on chrome (mobile) 80.
-     */
-    export class WebXRHitTest extends WebXRAbstractFeature {
-        /**
-         * options to use when constructing this feature
-         */
-        readonly options: IWebXRHitTestOptions;
-        private _tmpMat;
-        private _tmpPos;
-        private _tmpQuat;
-        private _transientXrHitTestSource;
-        private _xrHitTestSource;
-        private initHitTestSource;
-        /**
-         * The module's name
-         */
-        static readonly Name: string;
-        /**
-         * The (Babylon) version of this module.
-         * This is an integer representing the implementation version.
-         * This number does not correspond to the WebXR specs version
-         */
-        static readonly Version: number;
-        /**
-         * When set to true, each hit test will have its own position/rotation objects
-         * When set to false, position and rotation objects will be reused for each hit test. It is expected that
-         * the developers will clone them or copy them as they see fit.
-         */
-        autoCloneTransformation: boolean;
-        /**
-         * Populated with the last native XR Hit Results
-         */
-        lastNativeXRHitResults: XRHitResult[];
-        /**
-         * Triggered when new babylon (transformed) hit test results are available
-         */
-        onHitTestResultObservable: Observable<IWebXRHitResult[]>;
-        /**
-         * Use this to temporarily pause hit test checks.
-         */
-        paused: boolean;
-        /**
-         * Creates a new instance of the hit test feature
-         * @param _xrSessionManager an instance of WebXRSessionManager
-         * @param options options to use when constructing this feature
-         */
-        constructor(_xrSessionManager: WebXRSessionManager, 
-        /**
-         * options to use when constructing this feature
-         */
-        options?: IWebXRHitTestOptions);
-        /**
-         * attach this feature
-         * Will usually be called by the features manager
-         *
-         * @returns true if successful.
-         */
-        attach(): boolean;
-        /**
-         * detach this feature.
-         * Will usually be called by the features manager
-         *
-         * @returns true if successful.
-         */
-        detach(): boolean;
-        /**
-         * Dispose this feature and all of the resources attached
-         */
-        dispose(): void;
-        protected _onXRFrame(frame: XRFrame): void;
-        private _processWebXRHitTestResult;
-    }
-}
-declare module BABYLON {
-    /**
      * The motion controller class for all microsoft mixed reality controllers
      */
     export class WebXRMicrosoftMixedRealityController extends WebXRAbstractMotionController {
@@ -73574,7 +73602,7 @@ interface XRSessionInit {
     requiredFeatures?: string[];
 }
 
-interface XRSession extends XRAnchorCreator {
+interface XRSession {
     addEventListener: Function;
     removeEventListener: Function;
     requestReferenceSpace(type: XRReferenceSpaceType): Promise<XRReferenceSpace>;
@@ -73615,6 +73643,7 @@ interface XRFrame {
     getHitTestResultsForTransientInput(hitTestSource: XRTransientInputHitTestSource): Array<XRTransientInputHitTestResult>;
     // Anchors
     trackedAnchors?: XRAnchorSet;
+    createAnchor(pose: XRRigidTransform, space: XRSpace): Promise<XRAnchor>;
     // Planes
     worldInformation: {
         detectedPlanes?: XRPlaneSet;
@@ -73699,6 +73728,8 @@ interface XRTransientInputHitTestResult {
 
 interface XRHitTestResult {
     getPose(baseSpace: XRSpace): XRPose | undefined;
+    // When anchor system is enabled
+    createAnchor?(pose: XRRigidTransform): Promise<XRAnchor>;
 }
 
 interface XRHitTestSource {
@@ -73722,23 +73753,15 @@ interface XRTransientInputHitTestOptionsInit {
 }
 
 interface XRAnchor {
-    // remove?
-    id?: string;
     anchorSpace: XRSpace;
-    lastChangedTime: number;
-    detach(): void;
+    delete(): void;
 }
 
-interface XRPlane extends XRAnchorCreator {
+interface XRPlane {
     orientation: "Horizontal" | "Vertical";
     planeSpace: XRSpace;
     polygon: Array<DOMPointReadOnly>;
     lastChangedTime: number;
-}
-
-interface XRAnchorCreator {
-    // AR Anchors
-    createAnchor(pose: XRPose | XRRigidTransform, referenceSpace: XRReferenceSpace): Promise<XRAnchor>;
 }
 
 /**
@@ -79166,6 +79189,8 @@ declare module BABYLON.GLTF2 {
         _forAssetContainer: boolean;
         /** Storage */
         _babylonLights: Light[];
+        /** @hidden */
+        _disableInstancedMesh: number;
         private _disposed;
         private _parent;
         private _state;

+ 48 - 48
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_Maths_math_vector__) {
+})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_perfCounter__) {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
@@ -366,7 +366,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_perfCounter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/perfCounter */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/perfCounter */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0__);
 
 /**
@@ -509,7 +509,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -1481,7 +1481,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _textBlock__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./textBlock */ "./2D/controls/textBlock.ts");
 /* harmony import */ var _image__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./image */ "./2D/controls/image.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5__);
 
 
@@ -1713,7 +1713,7 @@ babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5__["_TypeStore"].RegisteredTy
 __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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -1896,7 +1896,7 @@ babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].RegisteredT
 __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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -3285,7 +3285,7 @@ babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].RegisteredT
 __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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/logger */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -3700,7 +3700,7 @@ babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].RegisteredTypes
 "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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -5626,7 +5626,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DisplayGrid", function() { return DisplayGrid; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__);
 
 
@@ -5859,7 +5859,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__);
 
 
@@ -5956,7 +5956,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* 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");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__);
 
 
@@ -6414,7 +6414,7 @@ babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__["_TypeStore"].RegisteredTypes[
 __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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
 
@@ -7341,7 +7341,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InputPassword", function() { return InputPassword; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _inputText__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./inputText */ "./2D/controls/inputText.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__);
 
 
@@ -7380,7 +7380,7 @@ babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__["_TypeStore"].RegisteredTy
 __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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -8393,7 +8393,7 @@ babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].RegisteredT
 __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_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__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");
@@ -8664,7 +8664,7 @@ babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].Registere
 __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/Maths/math.vector");
+/* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/abstractMesh */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -8934,7 +8934,7 @@ babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].Registe
 __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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -9141,7 +9141,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Rectangle", function() { return Rectangle; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__);
 
 
@@ -9291,7 +9291,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _scrollViewerWindow__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./scrollViewerWindow */ "./2D/controls/scrollViewers/scrollViewerWindow.ts");
 /* harmony import */ var _sliders_scrollBar__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../sliders/scrollBar */ "./2D/controls/sliders/scrollBar.ts");
 /* harmony import */ var _sliders_imageScrollBar__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../sliders/imageScrollBar */ "./2D/controls/sliders/imageScrollBar.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_7__);
 
 
@@ -10914,7 +10914,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -11244,7 +11244,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _baseSlider__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./baseSlider */ "./2D/controls/sliders/baseSlider.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../measure */ "./2D/measure.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__);
 
 
@@ -11837,7 +11837,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Slider", function() { return Slider; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _baseSlider__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./baseSlider */ "./2D/controls/sliders/baseSlider.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__);
 
 
@@ -12092,7 +12092,7 @@ babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__["_TypeStore"].RegisteredTy
 __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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -12360,7 +12360,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -12823,7 +12823,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -13212,7 +13212,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_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__);
 
 
@@ -13437,7 +13437,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_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__);
 
 var tmpRect = [
@@ -13586,7 +13586,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_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./valueAndUnit */ "./2D/valueAndUnit.ts");
 
@@ -13729,7 +13729,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
 
@@ -14035,7 +14035,7 @@ var ValueAndUnit = /** @class */ (function () {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "XmlLoader", function() { return XmlLoader; });
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_0__);
 
 /**
@@ -14354,7 +14354,7 @@ var XmlLoader = /** @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/Maths/math.vector");
+/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/perfCounter");
 /* 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");
 
@@ -14397,7 +14397,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_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__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");
@@ -14578,7 +14578,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/perfCounter");
 /* 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");
 
@@ -14735,7 +14735,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
 
@@ -15141,7 +15141,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -15227,7 +15227,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_Materials_standardMaterial__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Materials/standardMaterial */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Materials_standardMaterial__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Materials/standardMaterial */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Materials_standardMaterial__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_standardMaterial__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");
@@ -15721,7 +15721,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_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__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");
@@ -15776,7 +15776,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -15903,7 +15903,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -15989,7 +15989,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
 /* 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");
 
@@ -16114,7 +16114,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
 /* 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");
 
@@ -16305,7 +16305,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
 /* 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");
 
@@ -16572,7 +16572,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/decorators */ "babylonjs/Misc/perfCounter");
 /* 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");
@@ -16895,7 +16895,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/perfCounter");
 /* 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';
@@ -16917,7 +16917,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/Maths/math.vector");
+/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/perfCounter");
 /* 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';
@@ -16940,7 +16940,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_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__);
 
 
@@ -17242,14 +17242,14 @@ if (typeof globalObject !== "undefined") {
 
 /***/ }),
 
-/***/ "babylonjs/Maths/math.vector":
+/***/ "babylonjs/Misc/perfCounter":
 /*!****************************************************************************************************!*\
   !*** external {"root":"BABYLON","commonjs":"babylonjs","commonjs2":"babylonjs","amd":"babylonjs"} ***!
   \****************************************************************************************************/
 /*! no static exports found */
 /***/ (function(module, exports) {
 
-module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Maths_math_vector__;
+module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_perfCounter__;
 
 /***/ })
 

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/gui/babylon.gui.js.map


+ 17 - 26
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -290,15 +290,12 @@ var EXT_mesh_gpu_instancing = /** @class */ (function () {
     EXT_mesh_gpu_instancing.prototype.loadNodeAsync = function (context, node, assign) {
         var _this = this;
         return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__["GLTFLoader"].LoadExtensionAsync(context, node, this.name, function (extensionContext, extension) {
+            _this._loader._disableInstancedMesh++;
             var promise = _this._loader.loadNodeAsync("#/nodes/" + node.index, node, assign);
+            _this._loader._disableInstancedMesh--;
             if (!node._primitiveBabylonMeshes) {
                 return promise;
             }
-            // Hide the source meshes.
-            for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
-                var babylonMesh = _a[_i];
-                babylonMesh.isVisible = false;
-            }
             var promises = new Array();
             var instanceCount = 0;
             var loadAttribute = function (attribute) {
@@ -318,31 +315,23 @@ var EXT_mesh_gpu_instancing = /** @class */ (function () {
             loadAttribute("TRANSLATION");
             loadAttribute("ROTATION");
             loadAttribute("SCALE");
-            if (instanceCount == 0) {
-                return promise;
-            }
-            var digitLength = instanceCount.toString().length;
-            for (var i = 0; i < instanceCount; ++i) {
-                for (var _b = 0, _c = node._primitiveBabylonMeshes; _b < _c.length; _b++) {
-                    var babylonMesh = _c[_b];
-                    var instanceName = (babylonMesh.name || babylonMesh.id) + "_" + babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["StringTools"].PadNumber(i, digitLength);
-                    var babylonInstancedMesh = babylonMesh.createInstance(instanceName);
-                    babylonInstancedMesh.setParent(babylonMesh);
-                }
-            }
             return promise.then(function (babylonTransformNode) {
                 return Promise.all(promises).then(function (_a) {
                     var translationBuffer = _a[0], rotationBuffer = _a[1], scaleBuffer = _a[2];
+                    var matrices = new Float32Array(instanceCount * 16);
+                    babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[0].copyFromFloats(0, 0, 0); // translation
+                    babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Quaternion[0].copyFromFloats(0, 0, 0, 1); // rotation
+                    babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[1].copyFromFloats(1, 1, 1); // scale
+                    for (var i = 0; i < instanceCount; ++i) {
+                        translationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Vector3"].FromArrayToRef(translationBuffer, i * 3, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[0]);
+                        rotationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Quaternion"].FromArrayToRef(rotationBuffer, i * 4, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Quaternion[0]);
+                        scaleBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Vector3"].FromArrayToRef(scaleBuffer, i * 3, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[1]);
+                        babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Matrix"].ComposeToRef(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[1], babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Quaternion[0], babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[0], babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Matrix[0]);
+                        babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Matrix[0].copyToArray(matrices, i * 16);
+                    }
                     for (var _i = 0, _b = node._primitiveBabylonMeshes; _i < _b.length; _i++) {
                         var babylonMesh = _b[_i];
-                        var babylonInstancedMeshes = babylonMesh.getChildMeshes(true, function (node) { return node.isAnInstance; });
-                        for (var i = 0; i < instanceCount; ++i) {
-                            var babylonInstancedMesh = babylonInstancedMeshes[i];
-                            translationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Vector3"].FromArrayToRef(translationBuffer, i * 3, babylonInstancedMesh.position);
-                            rotationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Quaternion"].FromArrayToRef(rotationBuffer, i * 4, babylonInstancedMesh.rotationQuaternion);
-                            scaleBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Vector3"].FromArrayToRef(scaleBuffer, i * 3, babylonInstancedMesh.scaling);
-                            babylonInstancedMesh.refreshBoundingInfo();
-                        }
+                        babylonMesh.thinInstanceSetBuffer("matrix", matrices, 16, true);
                     }
                     return babylonTransformNode;
                 });
@@ -2196,6 +2185,8 @@ var GLTFLoader = /** @class */ (function () {
         this._forAssetContainer = false;
         /** Storage */
         this._babylonLights = [];
+        /** @hidden */
+        this._disableInstancedMesh = 0;
         this._disposed = false;
         this._state = null;
         this._extensions = new Array();
@@ -2788,7 +2779,7 @@ var GLTFLoader = /** @class */ (function () {
             return extensionPromise;
         }
         this.logOpen("" + context);
-        var shouldInstance = this._parent.createInstances && (node.skin == undefined && !mesh.primitives[0].targets);
+        var shouldInstance = (this._disableInstancedMesh === 0) && this._parent.createInstances && (node.skin == undefined && !mesh.primitives[0].targets);
         var babylonAbstractMesh;
         var promise;
         if (shouldInstance && primitive._instanceData) {

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.js.map


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 17 - 26
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -2870,15 +2870,12 @@ var EXT_mesh_gpu_instancing = /** @class */ (function () {
     EXT_mesh_gpu_instancing.prototype.loadNodeAsync = function (context, node, assign) {
         var _this = this;
         return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__["GLTFLoader"].LoadExtensionAsync(context, node, this.name, function (extensionContext, extension) {
+            _this._loader._disableInstancedMesh++;
             var promise = _this._loader.loadNodeAsync("#/nodes/" + node.index, node, assign);
+            _this._loader._disableInstancedMesh--;
             if (!node._primitiveBabylonMeshes) {
                 return promise;
             }
-            // Hide the source meshes.
-            for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
-                var babylonMesh = _a[_i];
-                babylonMesh.isVisible = false;
-            }
             var promises = new Array();
             var instanceCount = 0;
             var loadAttribute = function (attribute) {
@@ -2898,31 +2895,23 @@ var EXT_mesh_gpu_instancing = /** @class */ (function () {
             loadAttribute("TRANSLATION");
             loadAttribute("ROTATION");
             loadAttribute("SCALE");
-            if (instanceCount == 0) {
-                return promise;
-            }
-            var digitLength = instanceCount.toString().length;
-            for (var i = 0; i < instanceCount; ++i) {
-                for (var _b = 0, _c = node._primitiveBabylonMeshes; _b < _c.length; _b++) {
-                    var babylonMesh = _c[_b];
-                    var instanceName = (babylonMesh.name || babylonMesh.id) + "_" + babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["StringTools"].PadNumber(i, digitLength);
-                    var babylonInstancedMesh = babylonMesh.createInstance(instanceName);
-                    babylonInstancedMesh.setParent(babylonMesh);
-                }
-            }
             return promise.then(function (babylonTransformNode) {
                 return Promise.all(promises).then(function (_a) {
                     var translationBuffer = _a[0], rotationBuffer = _a[1], scaleBuffer = _a[2];
+                    var matrices = new Float32Array(instanceCount * 16);
+                    babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[0].copyFromFloats(0, 0, 0); // translation
+                    babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Quaternion[0].copyFromFloats(0, 0, 0, 1); // rotation
+                    babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[1].copyFromFloats(1, 1, 1); // scale
+                    for (var i = 0; i < instanceCount; ++i) {
+                        translationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Vector3"].FromArrayToRef(translationBuffer, i * 3, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[0]);
+                        rotationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Quaternion"].FromArrayToRef(rotationBuffer, i * 4, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Quaternion[0]);
+                        scaleBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Vector3"].FromArrayToRef(scaleBuffer, i * 3, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[1]);
+                        babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Matrix"].ComposeToRef(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[1], babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Quaternion[0], babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[0], babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Matrix[0]);
+                        babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Matrix[0].copyToArray(matrices, i * 16);
+                    }
                     for (var _i = 0, _b = node._primitiveBabylonMeshes; _i < _b.length; _i++) {
                         var babylonMesh = _b[_i];
-                        var babylonInstancedMeshes = babylonMesh.getChildMeshes(true, function (node) { return node.isAnInstance; });
-                        for (var i = 0; i < instanceCount; ++i) {
-                            var babylonInstancedMesh = babylonInstancedMeshes[i];
-                            translationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Vector3"].FromArrayToRef(translationBuffer, i * 3, babylonInstancedMesh.position);
-                            rotationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Quaternion"].FromArrayToRef(rotationBuffer, i * 4, babylonInstancedMesh.rotationQuaternion);
-                            scaleBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Vector3"].FromArrayToRef(scaleBuffer, i * 3, babylonInstancedMesh.scaling);
-                            babylonInstancedMesh.refreshBoundingInfo();
-                        }
+                        babylonMesh.thinInstanceSetBuffer("matrix", matrices, 16, true);
                     }
                     return babylonTransformNode;
                 });
@@ -4776,6 +4765,8 @@ var GLTFLoader = /** @class */ (function () {
         this._forAssetContainer = false;
         /** Storage */
         this._babylonLights = [];
+        /** @hidden */
+        this._disableInstancedMesh = 0;
         this._disposed = false;
         this._state = null;
         this._extensions = new Array();
@@ -5368,7 +5359,7 @@ var GLTFLoader = /** @class */ (function () {
             return extensionPromise;
         }
         this.logOpen("" + context);
-        var shouldInstance = this._parent.createInstances && (node.skin == undefined && !mesh.primitives[0].targets);
+        var shouldInstance = (this._disableInstancedMesh === 0) && this._parent.createInstances && (node.skin == undefined && !mesh.primitives[0].targets);
         var babylonAbstractMesh;
         var promise;
         if (shouldInstance && primitive._instanceData) {

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.js.map


File diff suppressed because it is too large
+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


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

@@ -1328,6 +1328,8 @@ declare module BABYLON.GLTF2 {
         _forAssetContainer: boolean;
         /** Storage */
         _babylonLights: Light[];
+        /** @hidden */
+        _disableInstancedMesh: number;
         private _disposed;
         private _parent;
         private _state;

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

@@ -4250,15 +4250,12 @@ var EXT_mesh_gpu_instancing = /** @class */ (function () {
     EXT_mesh_gpu_instancing.prototype.loadNodeAsync = function (context, node, assign) {
         var _this = this;
         return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__["GLTFLoader"].LoadExtensionAsync(context, node, this.name, function (extensionContext, extension) {
+            _this._loader._disableInstancedMesh++;
             var promise = _this._loader.loadNodeAsync("#/nodes/" + node.index, node, assign);
+            _this._loader._disableInstancedMesh--;
             if (!node._primitiveBabylonMeshes) {
                 return promise;
             }
-            // Hide the source meshes.
-            for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
-                var babylonMesh = _a[_i];
-                babylonMesh.isVisible = false;
-            }
             var promises = new Array();
             var instanceCount = 0;
             var loadAttribute = function (attribute) {
@@ -4278,31 +4275,23 @@ var EXT_mesh_gpu_instancing = /** @class */ (function () {
             loadAttribute("TRANSLATION");
             loadAttribute("ROTATION");
             loadAttribute("SCALE");
-            if (instanceCount == 0) {
-                return promise;
-            }
-            var digitLength = instanceCount.toString().length;
-            for (var i = 0; i < instanceCount; ++i) {
-                for (var _b = 0, _c = node._primitiveBabylonMeshes; _b < _c.length; _b++) {
-                    var babylonMesh = _c[_b];
-                    var instanceName = (babylonMesh.name || babylonMesh.id) + "_" + babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["StringTools"].PadNumber(i, digitLength);
-                    var babylonInstancedMesh = babylonMesh.createInstance(instanceName);
-                    babylonInstancedMesh.setParent(babylonMesh);
-                }
-            }
             return promise.then(function (babylonTransformNode) {
                 return Promise.all(promises).then(function (_a) {
                     var translationBuffer = _a[0], rotationBuffer = _a[1], scaleBuffer = _a[2];
+                    var matrices = new Float32Array(instanceCount * 16);
+                    babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[0].copyFromFloats(0, 0, 0); // translation
+                    babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Quaternion[0].copyFromFloats(0, 0, 0, 1); // rotation
+                    babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[1].copyFromFloats(1, 1, 1); // scale
+                    for (var i = 0; i < instanceCount; ++i) {
+                        translationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Vector3"].FromArrayToRef(translationBuffer, i * 3, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[0]);
+                        rotationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Quaternion"].FromArrayToRef(rotationBuffer, i * 4, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Quaternion[0]);
+                        scaleBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Vector3"].FromArrayToRef(scaleBuffer, i * 3, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[1]);
+                        babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Matrix"].ComposeToRef(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[1], babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Quaternion[0], babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Vector3[0], babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Matrix[0]);
+                        babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["TmpVectors"].Matrix[0].copyToArray(matrices, i * 16);
+                    }
                     for (var _i = 0, _b = node._primitiveBabylonMeshes; _i < _b.length; _i++) {
                         var babylonMesh = _b[_i];
-                        var babylonInstancedMeshes = babylonMesh.getChildMeshes(true, function (node) { return node.isAnInstance; });
-                        for (var i = 0; i < instanceCount; ++i) {
-                            var babylonInstancedMesh = babylonInstancedMeshes[i];
-                            translationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Vector3"].FromArrayToRef(translationBuffer, i * 3, babylonInstancedMesh.position);
-                            rotationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Quaternion"].FromArrayToRef(rotationBuffer, i * 4, babylonInstancedMesh.rotationQuaternion);
-                            scaleBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__["Vector3"].FromArrayToRef(scaleBuffer, i * 3, babylonInstancedMesh.scaling);
-                            babylonInstancedMesh.refreshBoundingInfo();
-                        }
+                        babylonMesh.thinInstanceSetBuffer("matrix", matrices, 16, true);
                     }
                     return babylonTransformNode;
                 });
@@ -6156,6 +6145,8 @@ var GLTFLoader = /** @class */ (function () {
         this._forAssetContainer = false;
         /** Storage */
         this._babylonLights = [];
+        /** @hidden */
+        this._disableInstancedMesh = 0;
         this._disposed = false;
         this._state = null;
         this._extensions = new Array();
@@ -6748,7 +6739,7 @@ var GLTFLoader = /** @class */ (function () {
             return extensionPromise;
         }
         this.logOpen("" + context);
-        var shouldInstance = this._parent.createInstances && (node.skin == undefined && !mesh.primitives[0].targets);
+        var shouldInstance = (this._disableInstancedMesh === 0) && this._parent.createInstances && (node.skin == undefined && !mesh.primitives[0].targets);
         var babylonAbstractMesh;
         var promise;
         if (shouldInstance && primitive._instanceData) {

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.js.map


File diff suppressed because it is too large
+ 2 - 2
dist/preview release/loaders/babylonjs.loaders.min.js


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

@@ -1417,6 +1417,8 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
         _forAssetContainer: boolean;
         /** Storage */
         _babylonLights: Light[];
+        /** @hidden */
+        _disableInstancedMesh: number;
         private _disposed;
         private _parent;
         private _state;
@@ -4062,6 +4064,8 @@ declare module BABYLON.GLTF2 {
         _forAssetContainer: boolean;
         /** Storage */
         _babylonLights: Light[];
+        /** @hidden */
+        _disableInstancedMesh: number;
         private _disposed;
         private _parent;
         private _state;

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

@@ -1 +1 @@
-{"thinEngineOnly":115966,"engineOnly":152369,"sceneOnly":511651,"minGridMaterial":647483,"minStandardMaterial":791596}
+{"thinEngineOnly":115966,"engineOnly":152369,"sceneOnly":511651,"minGridMaterial":647502,"minStandardMaterial":791615}

File diff suppressed because it is too large
+ 487 - 436
dist/preview release/viewer/babylon.module.d.ts


File diff suppressed because it is too large
+ 117 - 113
dist/preview release/viewer/babylon.viewer.js


File diff suppressed because it is too large
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -1417,6 +1417,8 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
         _forAssetContainer: boolean;
         /** Storage */
         _babylonLights: Light[];
+        /** @hidden */
+        _disableInstancedMesh: number;
         private _disposed;
         private _parent;
         private _state;
@@ -4062,6 +4064,8 @@ declare module BABYLON.GLTF2 {
         _forAssetContainer: boolean;
         /** Storage */
         _babylonLights: Light[];
+        /** @hidden */
+        _disableInstancedMesh: number;
         private _disposed;
         private _parent;
         private _state;

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

@@ -117,6 +117,7 @@
 - Added support for (experimental) haptic actuators ([#8068](https://github.com/BabylonJS/Babylon.js/issues/8068)) ([RaananW](https://github.com/RaananW))
 - It is now possible to enable experimental (AR) features using the options of the default xr helper ([RaananW](https://github.com/RaananW))
 - Full support for right handed systems ([#8132](https://github.com/BabylonJS/Babylon.js/issues/8132)) ([RaananW](https://github.com/RaananW))
+- WebXR anchors feature ([#7917](https://github.com/BabylonJS/Babylon.js/issues/7917)) ([RaananW](https://github.com/RaananW))
 
 ### Collisions
 
@@ -153,6 +154,10 @@
 - Added support for code templates in the playground ([sailro](http://www.github.com/sailro))
 - If createEngine fails, a default engine will be created ([#8084](https://github.com/BabylonJS/Babylon.js/issues/8084)) ([RaananW](https://github.com/RaananW))
 
+### GUI
+
+- Added support for custom word splitting function for `TextBlock` ([Popov72](https://github.com/Popov72))
+
 ## Bugs
 
 - Fix infinite loop in `GlowLayer.unReferenceMeshFromUsingItsOwnMaterial` ([Popov72](https://github.com/Popov72))
@@ -204,6 +209,7 @@
 - Fixed an issue with transformation set after physics body was created using cannon.js ([#7928](https://github.com/BabylonJS/Babylon.js/issues/7928)) ([RaananW](https://github.com/RaananW))
 - Fix bug when using `ShadowOnlyMaterial` with Cascaded Shadow Map and `autoCalcDepthBounds` is `true` ([Popov72](https://github.com/Popov72))
 - Fix OBJ serializer default scene scene handedness causing [OBJ Mirror export](https://forum.babylonjs.com/t/obj-export-mirrored/10835/10)
+- Fix bug when using shadows + instances + transparent meshes + `transparencyShadow = false` ([Popov72](https://github.com/Popov72))
 
 ## Breaking changes
 

+ 6 - 1
gui/src/2D/controls/textBlock.ts

@@ -50,6 +50,11 @@ export class TextBlock extends Control {
     public onLinesReadyObservable = new Observable<TextBlock>();
 
     /**
+     * Function used to split a string into words. By default, a string is split at each space character found
+     */
+    public wordSplittingFunction: Nullable<(line: string) => string[]>;
+
+    /**
      * Return the line list (you may need to use the onLinesReadyObservable to make sure the list is ready)
      */
     public get lines(): any[] {
@@ -368,7 +373,7 @@ export class TextBlock extends Control {
     protected _parseLineWordWrap(line: string = '', width: number,
         context: CanvasRenderingContext2D): object[] {
         var lines = [];
-        var words = line.split(' ');
+        var words = this.wordSplittingFunction ? this.wordSplittingFunction(line) : line.split(' ');
         var lineWidth = 0;
 
         for (var n = 0; n < words.length; n++) {

+ 3 - 2
inspector/src/components/actionTabs/tabs/propertyGrids/animations/anchorSvgPoint.tsx

@@ -8,6 +8,7 @@ interface IAnchorSvgPointProps {
    active: boolean;
    type: string;
    index: string;
+   selected: boolean;
 }
 
 
@@ -20,9 +21,9 @@ export class AnchorSvgPoint extends React.Component<IAnchorSvgPointProps>{
         return (
         <>
             <svg x={this.props.control.x} y={this.props.control.y} style={{overflow:'visible'}}>
-                <circle type={this.props.type} data-id={this.props.index} className="draggable control-point" cx="0" cy="0"  r="2" stroke="none" strokeWidth="0" fill={this.props.active ? "blue" : "black"}   />
+                <circle type={this.props.type} data-id={this.props.index} className={`draggable control-point ${this.props.active ? 'active' : ''}`} cx="0" cy="0"  r="2" stroke="none" strokeWidth="0" fill={this.props.active ? "blue" : "black"}   />
             </svg>
-            <line x1={this.props.anchor.x} y1={this.props.anchor.y} x2={this.props.control.x} y2={this.props.control.y} stroke="green" strokeWidth="0.75" />
+            <line className={`control-point ${this.props.active ? 'active' : ''}`} x1={this.props.anchor.x} y1={this.props.anchor.y} x2={this.props.control.x} y2={this.props.control.y} stroke="green" strokeWidth="0.75" />
         </>
         )
     }

File diff suppressed because it is too large
+ 210 - 23
inspector/src/components/actionTabs/tabs/propertyGrids/animations/animationCurveEditorComponent.tsx


+ 21 - 1
inspector/src/components/actionTabs/tabs/propertyGrids/animations/curveEditor.scss

@@ -142,7 +142,17 @@
             ul {
                 list-style:none;
                 padding-left: 0px;
+                li.property {
+                    &:before {
+                        content: '';
+                        background: none;
+                    }
+                }
                 li {
+                    p {
+                        font-weight: bolder;
+                        font-variant: all-small-caps;
+                    }
                     cursor: pointer;
                     &:before {
                         content: '';
@@ -170,7 +180,9 @@
                 background-color: rgba(0, 0, 0, 0.3);
                 padding: 10px;
                 margin-top: 19px;
-                height: 15em;
+                height: 11em;
+                overflow: scroll;
+                overflow-x: hidden;
             }
 
             .label-input{
@@ -218,6 +230,14 @@
                 text {
                     fill: #cecece;
                 }
+
+                .control-point {
+                    display: none;
+                }
+
+                .control-point.active {
+                    display: inline;
+                }
             }
 
             .playhead-wrapper {

+ 9 - 1
inspector/src/components/actionTabs/tabs/propertyGrids/animations/graphActionsBar.tsx

@@ -4,9 +4,12 @@ import { ButtonLineComponent } from '../../../lines/buttonLineComponent';
 
 interface IGraphActionsBarProps {
    addKeyframe: () => void;
+   removeKeyframe: () => void;
    handleValueChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
+   handleFrameChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
    flatTangent: () => void;
    currentValue: number;
+   currentFrame: number;
 }
 
 export class GraphActionsBar extends React.Component<IGraphActionsBarProps>{ 
@@ -18,10 +21,15 @@ export class GraphActionsBar extends React.Component<IGraphActionsBarProps>{
        return (
            <div className="actions-wrapper">
                <div className="action-input">
+               <label>Frame</label>
+               <input type="number" value={this.props.currentFrame} onChange={this.props.handleFrameChange} step="1"/>
+               </div>
+               <div className="action-input">
                <label>Value</label>
-               <input type="number" value={this.props.currentValue} onChange={this.props.handleValueChange}/>
+               <input type="number" value={this.props.currentValue.toFixed(3)} onChange={this.props.handleValueChange} step="0.001"/>
                </div>
               <ButtonLineComponent label={"Add Keyframe"} onClick={this.props.addKeyframe} />
+              <ButtonLineComponent label={"Remove Keyframe"} onClick={this.props.removeKeyframe} />
               <ButtonLineComponent label={"Flat Tangent"} onClick={this.props.flatTangent} />
            </div>
         )

+ 2 - 2
inspector/src/components/actionTabs/tabs/propertyGrids/animations/keyframeSvgPoint.tsx

@@ -28,8 +28,8 @@ export class KeyframeSvgPoint extends React.Component<IKeyframeSvgPointProps>{
                 <svg className="draggable" x={this.props.keyframePoint.x} y={this.props.keyframePoint.y} style={{overflow:'visible'}}>
                     <circle data-id={this.props.id} className="draggable" cx="0" cy="0"  r="2" stroke="none" strokeWidth="0" fill="red" />
                 </svg>
-               { this.props.leftControlPoint && <AnchorSvgPoint type="left" index={this.props.id} control={this.props.leftControlPoint} anchor={this.props.keyframePoint} active={false}/>} 
-               { this.props.rightControlPoint &&  <AnchorSvgPoint type="right" index={this.props.id} control={this.props.rightControlPoint} anchor={this.props.keyframePoint} active={false}/>}
+               { this.props.leftControlPoint && <AnchorSvgPoint type="left" index={this.props.id} control={this.props.leftControlPoint} anchor={this.props.keyframePoint} active={false} selected={false}/>} 
+               { this.props.rightControlPoint &&  <AnchorSvgPoint type="right" index={this.props.id} control={this.props.rightControlPoint} anchor={this.props.keyframePoint} active={false} selected={false}/>}
             </>
         )
     }

+ 23 - 30
loaders/src/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.ts

@@ -1,13 +1,11 @@
-import { Vector3, Quaternion } from 'babylonjs/Maths/math.vector';
-import { InstancedMesh } from 'babylonjs/Meshes/instancedMesh';
+import { Vector3, Quaternion, Matrix } from 'babylonjs/Maths/math.vector';
 import { Mesh } from 'babylonjs/Meshes/mesh';
 import { TransformNode } from "babylonjs/Meshes/transformNode";
-import { StringTools } from 'babylonjs/Misc/stringTools';
 import { Nullable } from "babylonjs/types";
 import { GLTFLoader, ArrayItem } from "../glTFLoader";
 import { IGLTFLoaderExtension } from "../glTFLoaderExtension";
 import { INode } from "../glTFLoaderInterfaces";
-import { AbstractMesh } from 'babylonjs/Meshes/abstractMesh';
+import { TmpVectors } from 'babylonjs/Maths/math.vector';
 
 const NAME = "EXT_mesh_gpu_instancing";
 
@@ -48,17 +46,16 @@ export class EXT_mesh_gpu_instancing implements IGLTFLoaderExtension {
     /** @hidden */
     public loadNodeAsync(context: string, node: INode, assign: (babylonTransformNode: TransformNode) => void): Nullable<Promise<TransformNode>> {
         return GLTFLoader.LoadExtensionAsync<IEXTMeshGpuInstancing, TransformNode>(context, node, this.name, (extensionContext, extension) => {
+            this._loader._disableInstancedMesh++;
+
             const promise = this._loader.loadNodeAsync(`#/nodes/${node.index}`, node, assign);
 
+            this._loader._disableInstancedMesh--;
+
             if (!node._primitiveBabylonMeshes) {
                 return promise;
             }
 
-            // Hide the source meshes.
-            for (const babylonMesh of node._primitiveBabylonMeshes) {
-                babylonMesh.isVisible = false;
-            }
-
             const promises = new Array<Promise<Nullable<Float32Array>>>();
             let instanceCount = 0;
 
@@ -82,30 +79,26 @@ export class EXT_mesh_gpu_instancing implements IGLTFLoaderExtension {
             loadAttribute("ROTATION");
             loadAttribute("SCALE");
 
-            if (instanceCount == 0) {
-                return promise;
-            }
-
-            const digitLength = instanceCount.toString().length;
-            for (let i = 0; i < instanceCount; ++i) {
-                for (const babylonMesh of node._primitiveBabylonMeshes!) {
-                    const instanceName = `${babylonMesh.name || babylonMesh.id}_${StringTools.PadNumber(i, digitLength)}`;
-                    const babylonInstancedMesh = (babylonMesh as (InstancedMesh | Mesh)).createInstance(instanceName);
-                    babylonInstancedMesh.setParent(babylonMesh);
-                }
-            }
-
             return promise.then((babylonTransformNode) => {
                 return Promise.all(promises).then(([translationBuffer, rotationBuffer, scaleBuffer]) => {
+                    const matrices = new Float32Array(instanceCount * 16);
+
+                    TmpVectors.Vector3[0].copyFromFloats(0, 0, 0); // translation
+                    TmpVectors.Quaternion[0].copyFromFloats(0, 0, 0, 1); // rotation
+                    TmpVectors.Vector3[1].copyFromFloats(1, 1, 1); // scale
+
+                    for (let i = 0; i < instanceCount; ++i) {
+                        translationBuffer && Vector3.FromArrayToRef(translationBuffer, i * 3, TmpVectors.Vector3[0]);
+                        rotationBuffer && Quaternion.FromArrayToRef(rotationBuffer, i * 4, TmpVectors.Quaternion[0]);
+                        scaleBuffer && Vector3.FromArrayToRef(scaleBuffer, i * 3, TmpVectors.Vector3[1]);
+
+                        Matrix.ComposeToRef(TmpVectors.Vector3[1], TmpVectors.Quaternion[0], TmpVectors.Vector3[0], TmpVectors.Matrix[0]);
+
+                        TmpVectors.Matrix[0].copyToArray(matrices, i * 16);
+                    }
+
                     for (const babylonMesh of node._primitiveBabylonMeshes!) {
-                        const babylonInstancedMeshes = babylonMesh.getChildMeshes(true, (node) => (node as AbstractMesh).isAnInstance);
-                        for (let i = 0; i < instanceCount; ++i) {
-                            const babylonInstancedMesh = babylonInstancedMeshes[i];
-                            translationBuffer && Vector3.FromArrayToRef(translationBuffer, i * 3, babylonInstancedMesh.position);
-                            rotationBuffer && Quaternion.FromArrayToRef(rotationBuffer, i * 4, babylonInstancedMesh.rotationQuaternion!);
-                            scaleBuffer && Vector3.FromArrayToRef(scaleBuffer, i * 3, babylonInstancedMesh.scaling);
-                            babylonInstancedMesh.refreshBoundingInfo();
-                        }
+                            (babylonMesh as Mesh).thinInstanceSetBuffer("matrix", matrices, 16, true);
                     }
 
                     return babylonTransformNode;

+ 4 - 1
loaders/src/glTF/2.0/glTFLoader.ts

@@ -106,6 +106,9 @@ export class GLTFLoader implements IGLTFLoader {
     /** Storage */
     public _babylonLights: Light[] = [];
 
+    /** @hidden */
+    public _disableInstancedMesh = 0;
+
     private _disposed = false;
     private _parent: GLTFFileLoader;
     private _state: Nullable<GLTFLoaderState> = null;
@@ -777,7 +780,7 @@ export class GLTFLoader implements IGLTFLoader {
 
         this.logOpen(`${context}`);
 
-        const shouldInstance = this._parent.createInstances && (node.skin == undefined && !mesh.primitives[0].targets);
+        const shouldInstance = (this._disableInstancedMesh === 0) && this._parent.createInstances && (node.skin == undefined && !mesh.primitives[0].targets);
 
         let babylonAbstractMesh: AbstractMesh;
         let promise: Promise<any>;

+ 2 - 2
src/Layers/effectLayer.ts

@@ -657,9 +657,9 @@ export abstract class EffectLayer {
 
         var material = subMesh.getMaterial();
         var ownerMesh = subMesh.getMesh();
-        var replacementMesh = ownerMesh._internalAbstractMeshDataInfo._actAsRegularMesh ? ownerMesh : null;
+        var replacementMesh = subMesh.getReplacementMesh();
         var renderingMesh = subMesh.getRenderingMesh();
-        var effectiveMesh = replacementMesh ? replacementMesh : renderingMesh;
+        var effectiveMesh = subMesh.getEffectiveMesh();
         var scene = this._scene;
         var engine = scene.getEngine();
 

+ 6 - 11
src/LibDeclarations/webxr.d.ts

@@ -73,7 +73,7 @@ interface XRSessionInit {
     requiredFeatures?: string[];
 }
 
-interface XRSession extends XRAnchorCreator {
+interface XRSession {
     addEventListener: Function;
     removeEventListener: Function;
     requestReferenceSpace(type: XRReferenceSpaceType): Promise<XRReferenceSpace>;
@@ -114,6 +114,7 @@ interface XRFrame {
     getHitTestResultsForTransientInput(hitTestSource: XRTransientInputHitTestSource): Array<XRTransientInputHitTestResult>;
     // Anchors
     trackedAnchors?: XRAnchorSet;
+    createAnchor(pose: XRRigidTransform, space: XRSpace): Promise<XRAnchor>;
     // Planes
     worldInformation: {
         detectedPlanes?: XRPlaneSet;
@@ -198,6 +199,8 @@ interface XRTransientInputHitTestResult {
 
 interface XRHitTestResult {
     getPose(baseSpace: XRSpace): XRPose | undefined;
+    // When anchor system is enabled
+    createAnchor?(pose: XRRigidTransform): Promise<XRAnchor>;
 }
 
 interface XRHitTestSource {
@@ -221,21 +224,13 @@ interface XRTransientInputHitTestOptionsInit {
 }
 
 interface XRAnchor {
-    // remove?
-    id?: string;
     anchorSpace: XRSpace;
-    lastChangedTime: number;
-    detach(): void;
+    delete(): void;
 }
 
-interface XRPlane extends XRAnchorCreator {
+interface XRPlane {
     orientation: "Horizontal" | "Vertical";
     planeSpace: XRSpace;
     polygon: Array<DOMPointReadOnly>;
     lastChangedTime: number;
-}
-
-interface XRAnchorCreator {
-    // AR Anchors
-    createAnchor(pose: XRPose | XRRigidTransform, referenceSpace: XRReferenceSpace): Promise<XRAnchor>;
 }

+ 6 - 4
src/Lights/Shadows/shadowGenerator.ts

@@ -1030,6 +1030,10 @@ export class ShadowGenerator implements IShadowGenerator {
             for (index = 0; index < transparentSubMeshes.length; index++) {
                 this._renderSubMeshForShadowMap(transparentSubMeshes.data[index], true);
             }
+        } else {
+            for (index = 0; index < transparentSubMeshes.length; index++) {
+                transparentSubMeshes.data[index].getEffectiveMesh()._internalAbstractMeshDataInfo._isActiveIntermediate = false;
+            }
         }
     }
 
@@ -1054,10 +1058,8 @@ export class ShadowGenerator implements IShadowGenerator {
     }
 
     protected _renderSubMeshForShadowMap(subMesh: SubMesh, isTransparent: boolean = false): void {
-        var ownerMesh = subMesh.getMesh();
-        var replacementMesh = ownerMesh._internalAbstractMeshDataInfo._actAsRegularMesh ? ownerMesh : null;
         var renderingMesh = subMesh.getRenderingMesh();
-        var effectiveMesh = replacementMesh ? replacementMesh : renderingMesh;
+        var effectiveMesh = subMesh.getEffectiveMesh();
         var scene = this._scene;
         var engine = scene.getEngine();
         let material = subMesh.getMaterial();
@@ -1072,7 +1074,7 @@ export class ShadowGenerator implements IShadowGenerator {
         engine.setState(material.backFaceCulling);
 
         // Managing instances
-        var batch = renderingMesh._getInstancesRenderList(subMesh._id, !!replacementMesh);
+        var batch = renderingMesh._getInstancesRenderList(subMesh._id, !!subMesh.getReplacementMesh());
         if (batch.mustReturn) {
             return;
         }

+ 1 - 1
src/Meshes/mesh.ts

@@ -430,7 +430,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
                 "hasInstances", "source", "worldMatrixInstancedBuffer", "hasLODLevels", "geometry", "isBlocked", "areNormalsFrozen",
                 "facetNb", "isFacetDataEnabled", "lightSources", "useBones", "isAnInstance", "collider", "edgesRenderer", "forward",
                 "up", "right", "absolutePosition", "absoluteScaling", "absoluteRotationQuaternion", "isWorldMatrixFrozen",
-                "nonUniformScaling", "behaviors", "worldMatrixFromCache"
+                "nonUniformScaling", "behaviors", "worldMatrixFromCache", "hasThinInstances"
             ], ["_poseMatrix"]);
 
             // Source mesh

+ 18 - 0
src/Meshes/subMesh.ts

@@ -196,6 +196,24 @@ export class SubMesh extends BaseSubMesh implements ICullable {
     }
 
     /**
+     * Returns the replacement mesh of the submesh
+     * @returns the replacement mesh (could be different from parent mesh)
+     */
+    public getReplacementMesh(): Nullable<AbstractMesh> {
+        return this._mesh._internalAbstractMeshDataInfo._actAsRegularMesh ? this._mesh : null;
+    }
+
+    /**
+     * Returns the effective mesh of the submesh
+     * @returns the effective mesh (could be different from parent mesh)
+     */
+    public getEffectiveMesh(): AbstractMesh {
+        const replacementMesh = this._mesh._internalAbstractMeshDataInfo._actAsRegularMesh ? this._mesh : null;
+
+        return replacementMesh ? replacementMesh : this._renderingMesh;
+    }
+
+    /**
      * Returns the submesh material
      * @returns null or the current material
      */

+ 7 - 0
src/Meshes/thinInstanceMesh.ts

@@ -250,8 +250,10 @@ Mesh.prototype.thinInstanceRefreshBoundingInfo = function(forceRefreshParentInfo
     const matrixData = this._thinInstanceDataStorage.matrixData;
 
     if (vectors.length === 0) {
+        const worldMatrix = this.getWorldMatrix();
         for (let v = 0; v < boundingInfo.boundingBox.vectors.length; ++v) {
             vectors.push(boundingInfo.boundingBox.vectors[v].clone());
+            Vector3.TransformCoordinatesToRef(vectors[v], worldMatrix, vectors[v]);
         }
     }
 
@@ -341,3 +343,8 @@ Mesh.prototype._disposeThinInstanceSpecificData = function() {
         this._thinInstanceDataStorage.matrixBuffer = null;
     }
 };
+
+/**
+ * @hidden
+ */
+export var _IDoNeedToBeInTheBuild2 = 42;

+ 2 - 4
src/PostProcesses/volumetricLightScatteringPostProcess.ts

@@ -294,10 +294,8 @@ export class VolumetricLightScatteringPostProcess extends PostProcess {
 
         // Custom render function for submeshes
         var renderSubMesh = (subMesh: SubMesh): void => {
-            var ownerMesh = subMesh.getMesh();
-            var replacementMesh = ownerMesh._internalAbstractMeshDataInfo._actAsRegularMesh ? ownerMesh : null;
             var renderingMesh = subMesh.getRenderingMesh();
-            var effectiveMesh = replacementMesh ? replacementMesh : renderingMesh;
+            var effectiveMesh = subMesh.getEffectiveMesh();
             if (this._meshExcluded(renderingMesh)) {
                 return;
             }
@@ -317,7 +315,7 @@ export class VolumetricLightScatteringPostProcess extends PostProcess {
             engine.setState(material.backFaceCulling);
 
             // Managing instances
-            var batch = renderingMesh._getInstancesRenderList(subMesh._id, !!replacementMesh);
+            var batch = renderingMesh._getInstancesRenderList(subMesh._id, !!subMesh.getReplacementMesh());
 
             if (batch.mustReturn) {
                 return;

+ 2 - 4
src/Rendering/depthRenderer.ts

@@ -94,10 +94,8 @@ export class DepthRenderer {
 
         // Custom render function
         var renderSubMesh = (subMesh: SubMesh): void => {
-            var ownerMesh = subMesh.getMesh();
-            var replacementMesh = ownerMesh._internalAbstractMeshDataInfo._actAsRegularMesh ? ownerMesh : null;
             var renderingMesh = subMesh.getRenderingMesh();
-            var effectiveMesh = replacementMesh ? replacementMesh : renderingMesh;
+            var effectiveMesh = subMesh.getEffectiveMesh();
             var scene = this._scene;
             var engine = scene.getEngine();
             let material = subMesh.getMaterial();
@@ -112,7 +110,7 @@ export class DepthRenderer {
             engine.setState(material.backFaceCulling, 0, false, scene.useRightHandedSystem);
 
             // Managing instances
-            var batch = renderingMesh._getInstancesRenderList(subMesh._id, !!replacementMesh);
+            var batch = renderingMesh._getInstancesRenderList(subMesh._id, !!subMesh.getReplacementMesh());
 
             if (batch.mustReturn) {
                 return;

+ 2 - 4
src/Rendering/geometryBufferRenderer.ts

@@ -393,10 +393,8 @@ export class GeometryBufferRenderer {
 
         // Custom render function
         var renderSubMesh = (subMesh: SubMesh): void => {
-            var ownerMesh = subMesh.getMesh();
-            var replacementMesh = ownerMesh._internalAbstractMeshDataInfo._actAsRegularMesh ? ownerMesh : null;
             var renderingMesh = subMesh.getRenderingMesh();
-            var effectiveMesh = replacementMesh ? replacementMesh : renderingMesh;
+            var effectiveMesh = subMesh.getEffectiveMesh();
             var scene = this._scene;
             var engine = scene.getEngine();
             let material = <any> subMesh.getMaterial();
@@ -424,7 +422,7 @@ export class GeometryBufferRenderer {
             engine.setState(material.backFaceCulling, 0, false, scene.useRightHandedSystem);
 
             // Managing instances
-            var batch = renderingMesh._getInstancesRenderList(subMesh._id, !!replacementMesh);
+            var batch = renderingMesh._getInstancesRenderList(subMesh._id, !!subMesh.getReplacementMesh());
 
             if (batch.mustReturn) {
                 return;

+ 167 - 90
src/XR/features/WebXRAnchorSystem.ts

@@ -1,29 +1,26 @@
-import { WebXRFeatureName } from '../webXRFeaturesManager';
+import { WebXRFeatureName, WebXRFeaturesManager } from '../webXRFeaturesManager';
 import { WebXRSessionManager } from '../webXRSessionManager';
 import { Observable } from '../../Misc/observable';
-import { Matrix } from '../../Maths/math.vector';
+import { Matrix, Vector3, Quaternion } from '../../Maths/math.vector';
 import { TransformNode } from '../../Meshes/transformNode';
-import { WebXRPlaneDetector } from './WebXRPlaneDetector';
-import { WebXRHitTestLegacy } from './WebXRHitTestLegacy';
 import { WebXRAbstractFeature } from './WebXRAbstractFeature';
+import { IWebXRHitResult } from './WebXRHitTest';
+import { Tools } from '../../Misc/tools';
 
 /**
  * Configuration options of the anchor system
  */
 export interface IWebXRAnchorSystemOptions {
     /**
-     * Should a new anchor be added every time a select event is triggered
-     */
-    addAnchorOnSelect?: boolean;
-    /**
-     * should the anchor system use plane detection.
-     * If set to true, the plane-detection feature should be set using setPlaneDetector
-     */
-    usePlaneDetection?: boolean;
-    /**
      * a node that will be used to convert local to world coordinates
      */
     worldParentNode?: TransformNode;
+
+    /**
+     * If set to true a reference of the created anchors will be kept until the next session starts
+     * If not defined, anchors will be removed from the array when the feature is detached or the session ended.
+     */
+    doNotRemoveAnchorsOnSessionEnded?: boolean;
 }
 
 /**
@@ -42,45 +39,45 @@ export interface IWebXRAnchor {
      * The native anchor object
      */
     xrAnchor: XRAnchor;
+
+    /**
+     * if defined, this object will be constantly updated by the anchor's position and rotation
+     */
+    attachedNode?: TransformNode;
+}
+
+/**
+ * An internal interface for a future (promise based) anchor
+ */
+interface IWebXRFutureAnchor {
+    /**
+     * A resolve function
+     */
+    resolve: (xrAnchor: XRAnchor) => void;
+    /**
+     * A reject function
+     */
+    reject: (msg?: string) => void;
+    /**
+     * The XR Transformation of the future anchor
+     */
+    xrTransformation: XRRigidTransform;
 }
 
 let anchorIdProvider = 0;
 
 /**
- * An implementation of the anchor system of WebXR.
- * Note that the current documented implementation is not available in any browser. Future implementations
- * will use the frame to create an anchor and not the session or a detected plane
+ * An implementation of the anchor system for WebXR.
  * For further information see https://github.com/immersive-web/anchors/
  */
 export class WebXRAnchorSystem extends WebXRAbstractFeature {
-    private _enabled: boolean = false;
-    private _hitTestModule: WebXRHitTestLegacy;
     private _lastFrameDetected: XRAnchorSet = new Set();
-    private _onSelect = (event: XRInputSourceEvent) => {
-        if (!this._options.addAnchorOnSelect) {
-            return;
-        }
-        const onResults = (results: XRHitResult[]) => {
-            if (results.length) {
-                const hitResult = results[0];
-                const transform = new XRRigidTransform(hitResult.hitMatrix);
-                // find the plane on which to add.
-                this.addAnchorAtRigidTransformation(transform);
-            }
-        };
 
-        // avoid the hit-test, if the hit-test module is defined
-        if (this._hitTestModule && !this._hitTestModule.options.testOnPointerDownOnly) {
-            onResults(this._hitTestModule.lastNativeXRHitResults);
-        }
-        WebXRHitTestLegacy.XRHitTestWithSelectEvent(event, this._xrSessionManager.referenceSpace).then(onResults);
+    private _trackedAnchors: Array<IWebXRAnchor> = [];
 
-        // API will soon change, will need to use the plane
-        this._planeDetector;
-    }
+    private _referenceSpaceForFrameAnchors: XRReferenceSpace;
 
-    private _planeDetector: WebXRPlaneDetector;
-    private _trackedAnchors: Array<IWebXRAnchor> = [];
+    private _futureAnchors: IWebXRFutureAnchor[] = [];
 
     /**
      * The module's name
@@ -108,6 +105,14 @@ export class WebXRAnchorSystem extends WebXRAbstractFeature {
     public onAnchorUpdatedObservable: Observable<IWebXRAnchor> = new Observable();
 
     /**
+     * Set the reference space to use for anchor creation, when not using a hit test.
+     * Will default to the session's reference space if not defined
+     */
+    public set referenceSpaceForFrameAnchors(referenceSpace: XRReferenceSpace) {
+        this._referenceSpaceForFrameAnchors = referenceSpace;
+    }
+
+    /**
      * constructs a new anchor system
      * @param _xrSessionManager an instance of WebXRSessionManager
      * @param _options configuration object for this feature
@@ -116,32 +121,79 @@ export class WebXRAnchorSystem extends WebXRAbstractFeature {
         super(_xrSessionManager);
     }
 
+    private _tmpVector = new Vector3();
+    private _tmpQuaternion = new Quaternion();
+
+    private _populateTmpTransformation(position: Vector3, rotationQuaternion: Quaternion) {
+        this._tmpVector.copyFrom(position);
+        this._tmpQuaternion.copyFrom(rotationQuaternion);
+        if (!this._xrSessionManager.scene.useRightHandedSystem) {
+            this._tmpVector.z *= -1;
+            this._tmpQuaternion.z *= -1;
+            this._tmpQuaternion.w *= -1;
+        }
+        return {
+            position: this._tmpVector,
+            rotationQuaternion: this._tmpQuaternion
+        };
+    }
+
     /**
-     * Add anchor at a specific XR point.
+     * Create a new anchor point using a hit test result at a specific point in the scene
+     * An anchor is tracked only after it is added to the trackerAnchors in xrFrame. The promise returned here does not yet guaranty that.
+     * Use onAnchorAddedObservable to get newly added anchors if you require tracking guaranty.
      *
-     * @param xrRigidTransformation xr-coordinates where a new anchor should be added
-     * @param anchorCreator the object o use to create an anchor with. either a session or a plane
-     * @returns a promise the fulfills when the anchor was created
+     * @param hitTestResult The hit test result to use for this anchor creation
+     * @param position an optional position offset for this anchor
+     * @param rotationQuaternion an optional rotation offset for this anchor
+     * @returns A promise that fulfills when the XR anchor was registered in the system (but not necessarily added to the tracked anchors)
      */
-    public addAnchorAtRigidTransformation(xrRigidTransformation: XRRigidTransform, anchorCreator?: XRAnchorCreator): Promise<XRAnchor> {
-        const creator = anchorCreator || this._xrSessionManager.session;
-        return creator.createAnchor(xrRigidTransformation, this._xrSessionManager.referenceSpace);
+    public async addAnchorPointUsingHitTestResultAsync(hitTestResult: IWebXRHitResult, position: Vector3 = new Vector3(), rotationQuaternion: Quaternion = new Quaternion()): Promise<XRAnchor> {
+        // convert to XR space (right handed) if needed
+        this._populateTmpTransformation(position, rotationQuaternion);
+        // the matrix that we'll use
+        const m = new XRRigidTransform({...this._tmpVector}, {...this._tmpQuaternion});
+        if (!hitTestResult.xrHitResult.createAnchor) {
+            throw new Error('Anchors not enabled in this browsed. Add "anchors" to optional features');
+        } else {
+            try {
+                return hitTestResult.xrHitResult.createAnchor(m);
+            }
+            catch (error) {
+                throw new Error(error);
+            }
+        }
     }
 
     /**
-     * attach this feature
-     * Will usually be called by the features manager
+     * Add a new anchor at a specific position and rotation
+     * This function will add a new anchor per default in the next available frame. Unless forced, the createAnchor function
+     * will be called in the next xrFrame loop to make sure that the anchor can be created correctly.
+     * An anchor is tracked only after it is added to the trackerAnchors in xrFrame. The promise returned here does not yet guaranty that.
+     * Use onAnchorAddedObservable to get newly added anchors if you require tracking guaranty.
      *
-     * @returns true if successful.
+     * @param position the position in which to add an anchor
+     * @param rotationQuaternion an optional rotation for the anchor transformation
+     * @param forceCreateInCurrentFrame force the creation of this anchor in the current frame. Must be called inside xrFrame loop!
+     * @returns A promise that fulfills when the XR anchor was registered in the system (but not necessarily added to the tracked anchors)
      */
-    public attach(): boolean {
-        if (!super.attach()) {
-            return false;
-        }
-        if (this._options.addAnchorOnSelect) {
-            this._xrSessionManager.session.addEventListener('select', this._onSelect, false);
+    public addAnchorAtPositionAndRotationAsync(position: Vector3, rotationQuaternion: Quaternion = new Quaternion(), forceCreateInCurrentFrame = false): Promise<XRAnchor> {
+        // convert to XR space (right handed) if needed
+        this._populateTmpTransformation(position, rotationQuaternion);
+        // the matrix that we'll use
+        const xrTransformation = new XRRigidTransform({...this._tmpVector}, {...this._tmpQuaternion});
+        if (forceCreateInCurrentFrame && this.attached && this._xrSessionManager.currentFrame) {
+            return this._createAnchorAtTransformation(xrTransformation, this._xrSessionManager.currentFrame);
+        } else {
+            // add the transformation to the future anchors list
+            return new Promise<XRAnchor>((resolve, reject) => {
+                this._futureAnchors.push({
+                    xrTransformation,
+                    resolve,
+                    reject
+                });
+            });
         }
-        return true;
     }
 
     /**
@@ -155,7 +207,14 @@ export class WebXRAnchorSystem extends WebXRAbstractFeature {
             return false;
         }
 
-        this._xrSessionManager.session.removeEventListener('select', this._onSelect);
+        if (!this._options.doNotRemoveAnchorsOnSessionEnded) {
+            while (this._trackedAnchors.length) {
+                const toRemove = this._trackedAnchors.pop();
+                if (toRemove) {
+                    this.onAnchorRemovedObservable.notifyObservers(toRemove);
+                }
+            }
+        }
 
         return true;
     }
@@ -170,33 +229,20 @@ export class WebXRAnchorSystem extends WebXRAbstractFeature {
         this.onAnchorUpdatedObservable.clear();
     }
 
-    /**
-     * If set, it will improve performance by using the current hit-test results instead of executing a new hit-test
-     * @param hitTestModule the hit-test module to use.
-     */
-    public setHitTestModule(hitTestModule: WebXRHitTestLegacy) {
-        this._hitTestModule = hitTestModule;
-    }
-
-    /**
-     * set the plane detector to use in order to create anchors from frames
-     * @param planeDetector the plane-detector module to use
-     * @param enable enable plane-anchors. default is true
-     */
-    public setPlaneDetector(planeDetector: WebXRPlaneDetector, enable: boolean = true) {
-        this._planeDetector = planeDetector;
-        this._options.usePlaneDetection = enable;
-    }
-
     protected _onXRFrame(frame: XRFrame) {
-        if (!this.attached || !this._enabled || !frame) { return; }
+        if (!this.attached || !frame) { return; }
 
         const trackedAnchors = frame.trackedAnchors;
-        if (trackedAnchors && trackedAnchors.size) {
-            this._trackedAnchors.filter((anchor) => !trackedAnchors.has(anchor.xrAnchor)).map((anchor) => {
+        if (trackedAnchors) {
+            const toRemove = this._trackedAnchors.filter((anchor) => !trackedAnchors.has(anchor.xrAnchor)).map((anchor) => {
                 const index = this._trackedAnchors.indexOf(anchor);
-                this._trackedAnchors.splice(index, 1);
+                return index;
+            });
+            let idxTracker = 0;
+            toRemove.forEach((index) => {
+                const anchor = this._trackedAnchors.splice(index - idxTracker, 1)[0];
                 this.onAnchorRemovedObservable.notifyObservers(anchor);
+                idxTracker--;
             });
             // now check for new ones
             trackedAnchors.forEach((xrAnchor) => {
@@ -205,21 +251,39 @@ export class WebXRAnchorSystem extends WebXRAbstractFeature {
                         id: anchorIdProvider++,
                         xrAnchor: xrAnchor
                     };
-                    const plane = this._updateAnchorWithXRFrame(xrAnchor, newAnchor, frame);
-                    this._trackedAnchors.push(plane);
-                    this.onAnchorAddedObservable.notifyObservers(plane);
+                    const anchor = this._updateAnchorWithXRFrame(xrAnchor, newAnchor, frame);
+                    this._trackedAnchors.push(anchor);
+                    this.onAnchorAddedObservable.notifyObservers(anchor);
                 } else {
-                    // updated?
-                    if (xrAnchor.lastChangedTime === this._xrSessionManager.currentTimestamp) {
-                        let index = this._findIndexInAnchorArray(xrAnchor);
-                        const anchor = this._trackedAnchors[index];
+                    let index = this._findIndexInAnchorArray(xrAnchor);
+                    const anchor = this._trackedAnchors[index];
+                    try {
+                        // anchors update every frame
                         this._updateAnchorWithXRFrame(xrAnchor, anchor, frame);
+                        if (anchor.attachedNode) {
+                            anchor.attachedNode.rotationQuaternion = anchor.attachedNode.rotationQuaternion || new Quaternion();
+                            anchor.transformationMatrix.decompose(anchor.attachedNode.scaling, anchor.attachedNode.rotationQuaternion, anchor.attachedNode.position);
+                        }
                         this.onAnchorUpdatedObservable.notifyObservers(anchor);
+                    } catch (e) {
+                        Tools.Warn(`Anchor could not be updated`);
                     }
                 }
             });
             this._lastFrameDetected = trackedAnchors;
         }
+
+        // process future anchors
+        while (this._futureAnchors.length) {
+            const futureAnchor = this._futureAnchors.pop();
+            if (!futureAnchor) {
+                return;
+            }
+            if (!frame.createAnchor) {
+                futureAnchor.reject('Anchors not enabled in this browser');
+            }
+            this._createAnchorAtTransformation(futureAnchor.xrTransformation, frame).then(futureAnchor.resolve, futureAnchor.reject);
+        }
     }
 
     /**
@@ -254,9 +318,22 @@ export class WebXRAnchorSystem extends WebXRAbstractFeature {
 
         return <IWebXRAnchor>anchor;
     }
+
+    private async _createAnchorAtTransformation(xrTransformation: XRRigidTransform, xrFrame: XRFrame) {
+        if (xrFrame.createAnchor) {
+            try {
+                return xrFrame.createAnchor(xrTransformation, this._referenceSpaceForFrameAnchors ?? this._xrSessionManager.referenceSpace);
+            }
+            catch (error) {
+                throw new Error(error);
+            }
+        } else {
+            throw new Error('Anchors are not enabled in your browser');
+        }
+    }
 }
 
 // register the plugin
-// WebXRFeaturesManager.AddWebXRFeature(WebXRAnchorSystem.Name, (xrSessionManager, options) => {
-//     return () => new WebXRAnchorSystem(xrSessionManager, options);
-// }, WebXRAnchorSystem.Version);
+WebXRFeaturesManager.AddWebXRFeature(WebXRAnchorSystem.Name, (xrSessionManager, options) => {
+    return () => new WebXRAnchorSystem(xrSessionManager, options);
+}, WebXRAnchorSystem.Version);

+ 12 - 8
src/XR/features/WebXRHitTest.ts

@@ -3,8 +3,9 @@ import { WebXRSessionManager } from '../webXRSessionManager';
 import { Observable } from '../../Misc/observable';
 import { Vector3, Matrix, Quaternion } from '../../Maths/math.vector';
 import { WebXRAbstractFeature } from './WebXRAbstractFeature';
-import { IWebXRLegacyHitTestOptions, IWebXRLegacyHitResult } from './WebXRHitTestLegacy';
+import { IWebXRLegacyHitTestOptions, IWebXRLegacyHitResult, IWebXRHitTestFeature } from './WebXRHitTestLegacy';
 import { Tools } from '../../Misc/tools';
+import { Nullable } from '../../types';
 
 /**
  * Options used for hit testing (version 2)
@@ -53,6 +54,11 @@ export interface IWebXRHitResult extends IWebXRLegacyHitResult {
      * Rotation of the hit test result
      */
     rotationQuaternion: Quaternion;
+
+    /**
+     * The native hit test result
+     */
+    xrHitResult: XRHitTestResult;
 }
 
 /**
@@ -62,13 +68,13 @@ export interface IWebXRHitResult extends IWebXRLegacyHitResult {
  *
  * Tested on chrome (mobile) 80.
  */
-export class WebXRHitTest extends WebXRAbstractFeature {
+export class WebXRHitTest extends WebXRAbstractFeature implements IWebXRHitTestFeature<IWebXRHitResult> {
     private _tmpMat: Matrix = new Matrix();
     private _tmpPos: Vector3 = new Vector3();
     private _tmpQuat: Quaternion = new Quaternion();
-    private _transientXrHitTestSource: XRTransientInputHitTestSource;
+    private _transientXrHitTestSource: Nullable<XRTransientInputHitTestSource>;
     // in XR space z-forward is negative
-    private _xrHitTestSource: XRHitTestSource;
+    private _xrHitTestSource: Nullable<XRHitTestSource>;
     private initHitTestSource = (referenceSpace: XRReferenceSpace) => {
         if (!referenceSpace) {
             return;
@@ -108,10 +114,6 @@ export class WebXRHitTest extends WebXRAbstractFeature {
      */
     public autoCloneTransformation: boolean = false;
     /**
-     * Populated with the last native XR Hit Results
-     */
-    public lastNativeXRHitResults: XRHitResult[] = [];
-    /**
      * Triggered when new babylon (transformed) hit test results are available
      */
     public onHitTestResultObservable: Observable<IWebXRHitResult[]> = new Observable();
@@ -176,10 +178,12 @@ export class WebXRHitTest extends WebXRAbstractFeature {
         }
         if (this._xrHitTestSource) {
             this._xrHitTestSource.cancel();
+            this._xrHitTestSource = null;
         }
         this._xrSessionManager.onXRReferenceSpaceChanged.removeCallback(this.initHitTestSource);
         if (this._transientXrHitTestSource) {
             this._transientXrHitTestSource.cancel();
+            this._transientXrHitTestSource = null;
         }
         return true;
     }

+ 12 - 2
src/XR/features/WebXRHitTestLegacy.ts

@@ -1,4 +1,4 @@
-import { WebXRFeaturesManager, WebXRFeatureName } from '../webXRFeaturesManager';
+import { WebXRFeaturesManager, WebXRFeatureName, IWebXRFeature } from '../webXRFeaturesManager';
 import { WebXRSessionManager } from '../webXRSessionManager';
 import { Observable } from '../../Misc/observable';
 import { Vector3, Matrix } from '../../Maths/math.vector';
@@ -8,6 +8,16 @@ import { WebXRAbstractFeature } from './WebXRAbstractFeature';
 // the plugin is registered at the end of the file
 
 /**
+ * An interface for all Hit test features
+ */
+export interface IWebXRHitTestFeature<T extends IWebXRLegacyHitResult> extends IWebXRFeature {
+    /**
+     * Triggered when new babylon (transformed) hit test results are available
+     */
+    onHitTestResultObservable: Observable<T[]>;
+}
+
+/**
  * Options used for hit testing
  */
 export interface IWebXRLegacyHitTestOptions {
@@ -40,7 +50,7 @@ export interface IWebXRLegacyHitResult {
  * Hit test (or Ray-casting) is used to interact with the real world.
  * For further information read here - https://github.com/immersive-web/hit-test
  */
-export class WebXRHitTestLegacy extends WebXRAbstractFeature {
+export class WebXRHitTestLegacy extends WebXRAbstractFeature  implements IWebXRHitTestFeature<IWebXRLegacyHitResult> {
     // in XR space z-forward is negative
     private _direction = new Vector3(0, 0, -1);
     private _mat = new Matrix();

+ 37 - 4
src/XR/features/WebXRPlaneDetector.ts

@@ -13,6 +13,12 @@ export interface IWebXRPlaneDetectorOptions {
      * The node to use to transform the local results to world coordinates
      */
     worldParentNode?: TransformNode;
+
+    /**
+     * If set to true a reference of the created planes will be kept until the next session starts
+     * If not defined, planes will be removed from the array when the feature is detached or the session ended.
+     */
+    doNotRemovePlanesOnSessionEnded?: boolean;
 }
 
 /**
@@ -94,6 +100,29 @@ export class WebXRPlaneDetector extends WebXRAbstractFeature {
     }
 
     /**
+     * detach this feature.
+     * Will usually be called by the features manager
+     *
+     * @returns true if successful.
+     */
+    public detach(): boolean {
+        if (!super.detach()) {
+            return false;
+        }
+
+        if (!this._options.doNotRemovePlanesOnSessionEnded) {
+            while (this._detectedPlanes.length) {
+                const toRemove = this._detectedPlanes.pop();
+                if (toRemove) {
+                    this.onPlaneRemovedObservable.notifyObservers(toRemove);
+                }
+            }
+        }
+
+        return true;
+    }
+
+    /**
      * Dispose this feature and all of the resources attached
      */
     public dispose(): void {
@@ -108,11 +137,15 @@ export class WebXRPlaneDetector extends WebXRAbstractFeature {
         // const timestamp = this.xrSessionManager.currentTimestamp;
 
         const detectedPlanes = frame.worldInformation.detectedPlanes;
-        if (detectedPlanes && detectedPlanes.size) {
-            this._detectedPlanes.filter((plane) => !detectedPlanes.has(plane.xrPlane)).map((plane) => {
-                const index = this._detectedPlanes.indexOf(plane);
-                this._detectedPlanes.splice(index, 1);
+        if (detectedPlanes) {
+            const toRemove = this._detectedPlanes.filter((plane) => !detectedPlanes.has(plane.xrPlane)).map((plane) => {
+                return this._detectedPlanes.indexOf(plane);
+            });
+            let idxTracker = 0;
+            toRemove.forEach((index) => {
+                const plane = this._detectedPlanes.splice(index - idxTracker, 1)[0];
                 this.onPlaneRemovedObservable.notifyObservers(plane);
+                idxTracker--;
             });
             // now check for new ones
             detectedPlanes.forEach((xrPlane) => {

+ 1 - 1
src/XR/webXRDefaultExperience.ts

@@ -144,7 +144,7 @@ export class WebXRDefaultExperience {
                 };
                 if (options.optionalFeatures) {
                     if (typeof options.optionalFeatures === 'boolean') {
-                        uiOptions.optionalFeatures = ['hit-test', 'anchors'/*, 'hand-tracking'*/];
+                        uiOptions.optionalFeatures = ['hit-test', 'anchors', 'planes', 'hand-tracking'];
                     } else {
                         uiOptions.optionalFeatures = options.optionalFeatures;
                     }

+ 3 - 0
src/XR/webXRInputSource.ts

@@ -5,6 +5,7 @@ import { Ray } from '../Culling/ray';
 import { Scene } from '../scene';
 import { WebXRAbstractMotionController } from './motionController/webXRAbstractMotionController';
 import { WebXRMotionControllerManager } from './motionController/webXRMotionControllerManager';
+import { Tools } from '../Misc/tools';
 
 let idCount = 0;
 
@@ -115,6 +116,8 @@ export class WebXRInputSource {
                         }
                     });
                 }
+            }, () => {
+                Tools.Warn(`Could not find a matching motion controller for the registered input source`);
             });
         }
     }

+ 2 - 1
tests/validation/config.json

@@ -835,7 +835,8 @@
         },
         {
             "title": "GLTF Extension EXT_mesh_gpu_instancing",
-            "playgroundId": "#QFIGLW#9",
+            "playgroundId": "#QFIGLW#9",            
+            "renderCount": 10,
             "referenceImage": "gltfExtensionExtMeshGpuInstancingTest.png"
         },
         {