Bladeren bron

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

Nicholas Barlow 5 jaren geleden
bovenliggende
commit
388e684deb
35 gewijzigde bestanden met toevoegingen van 513 en 62 verwijderingen
  1. 45 0
      dist/preview release/babylon.d.ts
  2. 1 1
      dist/preview release/babylon.js
  3. 89 15
      dist/preview release/babylon.max.js
  4. 1 1
      dist/preview release/babylon.max.js.map
  5. 92 0
      dist/preview release/babylon.module.d.ts
  6. 43 0
      dist/preview release/documentation.d.ts
  7. 0 1
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  8. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.js.map
  9. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  10. 0 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  11. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js.map
  12. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  13. 0 1
      dist/preview release/loaders/babylon.glTFFileLoader.js
  14. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.js.map
  15. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  16. 0 1
      dist/preview release/loaders/babylon.objFileLoader.js
  17. 1 1
      dist/preview release/loaders/babylon.objFileLoader.js.map
  18. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  19. 0 1
      dist/preview release/loaders/babylon.stlFileLoader.js
  20. 1 1
      dist/preview release/loaders/babylon.stlFileLoader.js.map
  21. 1 1
      dist/preview release/loaders/babylon.stlFileLoader.min.js
  22. 0 3
      dist/preview release/loaders/babylonjs.loaders.js
  23. 1 1
      dist/preview release/loaders/babylonjs.loaders.js.map
  24. 2 2
      dist/preview release/loaders/babylonjs.loaders.min.js
  25. 92 0
      dist/preview release/viewer/babylon.module.d.ts
  26. 9 9
      dist/preview release/viewer/babylon.viewer.js
  27. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  28. 1 1
      dist/preview release/what's new.md
  29. 0 1
      loaders/src/OBJ/objFileLoader.ts
  30. 0 1
      loaders/src/STL/stlFileLoader.ts
  31. 0 1
      loaders/src/glTF/glTFFileLoader.ts
  32. 5 0
      src/Loading/sceneLoader.ts
  33. 86 7
      src/XR/features/WebXRControllerPhysics.ts
  34. 32 1
      src/scene.ts
  35. 2 1
      tests/validation/config.json

+ 45 - 0
dist/preview release/babylon.d.ts

@@ -35096,6 +35096,8 @@ declare module BABYLON {
         cameraToUseForPointers: Nullable<Camera>;
         /** @hidden */
         readonly _isScene: boolean;
+        /** @hidden */
+        _blockEntityCollection: boolean;
         /**
          * Gets or sets a boolean that indicates if the scene must clear the render buffer before rendering a frame
          */
@@ -69064,6 +69066,35 @@ declare module BABYLON {
              */
             restitution?: number;
         };
+        /**
+         * Should the headset get its own impostor
+         */
+        enableHeadsetImpostor?: boolean;
+        /**
+         * Optional parameters for the headset impostor
+         */
+        headsetImpostorParams?: {
+            /**
+             * The type of impostor to create. Default is sphere
+             */
+            impostorType: number;
+            /**
+             * the size of the impostor. Defaults to 10cm
+             */
+            impostorSize?: number | {
+                width: number;
+                height: number;
+                depth: number;
+            };
+            /**
+             * Friction definitions
+             */
+            friction?: number;
+            /**
+             * Restitution
+             */
+            restitution?: number;
+        };
     }
     /**
      * Add physics impostor to your webxr controllers,
@@ -69084,6 +69115,8 @@ declare module BABYLON {
         private _lastTimestamp;
         private _delta;
         private _controllers;
+        private _headsetImpostor?;
+        private _headsetMesh?;
         private _tmpVector;
         private _tmpQuaternion;
         /**
@@ -69107,6 +69140,18 @@ declare module BABYLON {
             restitution?: number;
         }): void;
         /**
+         * Get the physics impostor of a specific controller.
+         * The impostor is not attached to a mesh because a mesh for each controller is not obligatory
+         * @param controller the controller or the controller id of which to get the impostor
+         * @returns the impostor or null
+         */
+        getImpostorForController(controller: WebXRInputSource | string): Nullable<PhysicsImpostor>;
+        /**
+         * Get the headset impostor, if enabled
+         * @returns the impostor
+         */
+        getHeadsetImpostor(): PhysicsImpostor | undefined;
+        /**
          * attach this feature
          * Will usually be called by the features manager
          *

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


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


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


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

@@ -36186,6 +36186,8 @@ declare module "babylonjs/scene" {
         cameraToUseForPointers: Nullable<Camera>;
         /** @hidden */
         readonly _isScene: boolean;
+        /** @hidden */
+        _blockEntityCollection: boolean;
         /**
          * Gets or sets a boolean that indicates if the scene must clear the render buffer before rendering a frame
          */
@@ -72770,8 +72772,10 @@ declare module "babylonjs/XR/features/WebXRBackgroundRemover" {
 declare module "babylonjs/XR/features/WebXRControllerPhysics" {
     import { WebXRAbstractFeature } from "babylonjs/XR/features/WebXRAbstractFeature";
     import { WebXRInputSource } from "babylonjs/XR/webXRInputSource";
+    import { PhysicsImpostor } from "babylonjs/Physics/physicsImpostor";
     import { WebXRInput } from "babylonjs/XR/webXRInput";
     import { WebXRSessionManager } from "babylonjs/XR/webXRSessionManager";
+    import { Nullable } from "babylonjs/types";
     /**
      * Options for the controller physics feature
      */
@@ -72810,6 +72814,35 @@ declare module "babylonjs/XR/features/WebXRControllerPhysics" {
              */
             restitution?: number;
         };
+        /**
+         * Should the headset get its own impostor
+         */
+        enableHeadsetImpostor?: boolean;
+        /**
+         * Optional parameters for the headset impostor
+         */
+        headsetImpostorParams?: {
+            /**
+             * The type of impostor to create. Default is sphere
+             */
+            impostorType: number;
+            /**
+             * the size of the impostor. Defaults to 10cm
+             */
+            impostorSize?: number | {
+                width: number;
+                height: number;
+                depth: number;
+            };
+            /**
+             * Friction definitions
+             */
+            friction?: number;
+            /**
+             * Restitution
+             */
+            restitution?: number;
+        };
     }
     /**
      * Add physics impostor to your webxr controllers,
@@ -72830,6 +72863,8 @@ declare module "babylonjs/XR/features/WebXRControllerPhysics" {
         private _lastTimestamp;
         private _delta;
         private _controllers;
+        private _headsetImpostor?;
+        private _headsetMesh?;
         private _tmpVector;
         private _tmpQuaternion;
         /**
@@ -72853,6 +72888,18 @@ declare module "babylonjs/XR/features/WebXRControllerPhysics" {
             restitution?: number;
         }): void;
         /**
+         * Get the physics impostor of a specific controller.
+         * The impostor is not attached to a mesh because a mesh for each controller is not obligatory
+         * @param controller the controller or the controller id of which to get the impostor
+         * @returns the impostor or null
+         */
+        getImpostorForController(controller: WebXRInputSource | string): Nullable<PhysicsImpostor>;
+        /**
+         * Get the headset impostor, if enabled
+         * @returns the impostor
+         */
+        getHeadsetImpostor(): PhysicsImpostor | undefined;
+        /**
          * attach this feature
          * Will usually be called by the features manager
          *
@@ -108328,6 +108375,8 @@ declare module BABYLON {
         cameraToUseForPointers: Nullable<Camera>;
         /** @hidden */
         readonly _isScene: boolean;
+        /** @hidden */
+        _blockEntityCollection: boolean;
         /**
          * Gets or sets a boolean that indicates if the scene must clear the render buffer before rendering a frame
          */
@@ -142296,6 +142345,35 @@ declare module BABYLON {
              */
             restitution?: number;
         };
+        /**
+         * Should the headset get its own impostor
+         */
+        enableHeadsetImpostor?: boolean;
+        /**
+         * Optional parameters for the headset impostor
+         */
+        headsetImpostorParams?: {
+            /**
+             * The type of impostor to create. Default is sphere
+             */
+            impostorType: number;
+            /**
+             * the size of the impostor. Defaults to 10cm
+             */
+            impostorSize?: number | {
+                width: number;
+                height: number;
+                depth: number;
+            };
+            /**
+             * Friction definitions
+             */
+            friction?: number;
+            /**
+             * Restitution
+             */
+            restitution?: number;
+        };
     }
     /**
      * Add physics impostor to your webxr controllers,
@@ -142316,6 +142394,8 @@ declare module BABYLON {
         private _lastTimestamp;
         private _delta;
         private _controllers;
+        private _headsetImpostor?;
+        private _headsetMesh?;
         private _tmpVector;
         private _tmpQuaternion;
         /**
@@ -142339,6 +142419,18 @@ declare module BABYLON {
             restitution?: number;
         }): void;
         /**
+         * Get the physics impostor of a specific controller.
+         * The impostor is not attached to a mesh because a mesh for each controller is not obligatory
+         * @param controller the controller or the controller id of which to get the impostor
+         * @returns the impostor or null
+         */
+        getImpostorForController(controller: WebXRInputSource | string): Nullable<PhysicsImpostor>;
+        /**
+         * Get the headset impostor, if enabled
+         * @returns the impostor
+         */
+        getHeadsetImpostor(): PhysicsImpostor | undefined;
+        /**
          * attach this feature
          * Will usually be called by the features manager
          *

+ 43 - 0
dist/preview release/documentation.d.ts

@@ -35096,6 +35096,8 @@ declare module BABYLON {
         cameraToUseForPointers: Nullable<Camera>;
         /** @hidden */
         readonly _isScene: boolean;
+        /** @hidden */
+        _blockEntityCollection: boolean;
         /**
          * Gets or sets a boolean that indicates if the scene must clear the render buffer before rendering a frame
          */
@@ -69064,6 +69066,35 @@ declare module BABYLON {
              */
             restitution?: number;
         };
+        /**
+         * Should the headset get its own impostor
+         */
+        enableHeadsetImpostor?: boolean;
+        /**
+         * Optional parameters for the headset impostor
+         */
+        headsetImpostorParams?: {
+            /**
+             * The type of impostor to create. Default is sphere
+             */
+            impostorType: number;
+            /**
+             * the size of the impostor. Defaults to 10cm
+             */
+            impostorSize?: number | {
+                width: number;
+                height: number;
+                depth: number;
+            };
+            /**
+             * Friction definitions
+             */
+            friction?: number;
+            /**
+             * Restitution
+             */
+            restitution?: number;
+        };
     }
     /**
      * Add physics impostor to your webxr controllers,
@@ -69084,6 +69115,8 @@ declare module BABYLON {
         private _lastTimestamp;
         private _delta;
         private _controllers;
+        private _headsetImpostor?;
+        private _headsetMesh?;
         private _tmpVector;
         private _tmpQuaternion;
         /**
@@ -69107,6 +69140,16 @@ declare module BABYLON {
             restitution?: number;
         }): void;
         /**
+         * Get the physics impostor of a specific controller.
+         * The impostor is not attached to a mesh because a mesh for each controller is not obligatory
+         * @param controller the controller or the controller id of which to get the impostor
+         */
+        getImpostorForController(controller: WebXRInputSource | string): Nullable<PhysicsImpostor>;
+        /**
+         * Get the headset impostor, if enabled
+         */
+        getHeadsetImpostor(): PhysicsImpostor | undefined;
+        /**
          * attach this feature
          * Will usually be called by the features manager
          *

+ 0 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -3194,7 +3194,6 @@ var GLTFFileLoader = /** @class */ (function () {
                 Array.prototype.push.apply(container.animationGroups, result.animationGroups);
                 Array.prototype.push.apply(container.materials, materials);
                 Array.prototype.push.apply(container.textures, textures);
-                container.removeAllFromScene();
                 return container;
             });
         });

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


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


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

@@ -4446,7 +4446,6 @@ var GLTFFileLoader = /** @class */ (function () {
                 Array.prototype.push.apply(container.animationGroups, result.animationGroups);
                 Array.prototype.push.apply(container.materials, materials);
                 Array.prototype.push.apply(container.textures, textures);
-                container.removeAllFromScene();
                 return container;
             });
         });

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


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

@@ -7006,7 +7006,6 @@ var GLTFFileLoader = /** @class */ (function () {
                 Array.prototype.push.apply(container.animationGroups, result.animationGroups);
                 Array.prototype.push.apply(container.materials, materials);
                 Array.prototype.push.apply(container.textures, textures);
-                container.removeAllFromScene();
                 return container;
             });
         });

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
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 0 - 1
dist/preview release/loaders/babylon.objFileLoader.js

@@ -585,7 +585,6 @@ var OBJFileLoader = /** @class */ (function () {
                     }
                 }
             });
-            container.removeAllFromScene();
             return container;
         });
     };

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


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


+ 0 - 1
dist/preview release/loaders/babylon.stlFileLoader.js

@@ -275,7 +275,6 @@ var STLFileLoader = /** @class */ (function () {
     STLFileLoader.prototype.loadAssetContainer = function (scene, data, rootUrl, onError) {
         var container = new babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__["AssetContainer"](scene);
         this.importMesh(null, scene, data, rootUrl, container.meshes, null, null);
-        container.removeAllFromScene();
         return container;
     };
     STLFileLoader.prototype._isBinary = function (data) {

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


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


+ 0 - 3
dist/preview release/loaders/babylonjs.loaders.js

@@ -814,7 +814,6 @@ var OBJFileLoader = /** @class */ (function () {
                     }
                 }
             });
-            container.removeAllFromScene();
             return container;
         });
     };
@@ -1627,7 +1626,6 @@ var STLFileLoader = /** @class */ (function () {
     STLFileLoader.prototype.loadAssetContainer = function (scene, data, rootUrl, onError) {
         var container = new babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__["AssetContainer"](scene);
         this.importMesh(null, scene, data, rootUrl, container.meshes, null, null);
-        container.removeAllFromScene();
         return container;
     };
     STLFileLoader.prototype._isBinary = function (data) {
@@ -8373,7 +8371,6 @@ var GLTFFileLoader = /** @class */ (function () {
                 Array.prototype.push.apply(container.animationGroups, result.animationGroups);
                 Array.prototype.push.apply(container.materials, materials);
                 Array.prototype.push.apply(container.textures, textures);
-                container.removeAllFromScene();
                 return container;
             });
         });

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


+ 92 - 0
dist/preview release/viewer/babylon.module.d.ts

@@ -36186,6 +36186,8 @@ declare module "babylonjs/scene" {
         cameraToUseForPointers: Nullable<Camera>;
         /** @hidden */
         readonly _isScene: boolean;
+        /** @hidden */
+        _blockEntityCollection: boolean;
         /**
          * Gets or sets a boolean that indicates if the scene must clear the render buffer before rendering a frame
          */
@@ -72770,8 +72772,10 @@ declare module "babylonjs/XR/features/WebXRBackgroundRemover" {
 declare module "babylonjs/XR/features/WebXRControllerPhysics" {
     import { WebXRAbstractFeature } from "babylonjs/XR/features/WebXRAbstractFeature";
     import { WebXRInputSource } from "babylonjs/XR/webXRInputSource";
+    import { PhysicsImpostor } from "babylonjs/Physics/physicsImpostor";
     import { WebXRInput } from "babylonjs/XR/webXRInput";
     import { WebXRSessionManager } from "babylonjs/XR/webXRSessionManager";
+    import { Nullable } from "babylonjs/types";
     /**
      * Options for the controller physics feature
      */
@@ -72810,6 +72814,35 @@ declare module "babylonjs/XR/features/WebXRControllerPhysics" {
              */
             restitution?: number;
         };
+        /**
+         * Should the headset get its own impostor
+         */
+        enableHeadsetImpostor?: boolean;
+        /**
+         * Optional parameters for the headset impostor
+         */
+        headsetImpostorParams?: {
+            /**
+             * The type of impostor to create. Default is sphere
+             */
+            impostorType: number;
+            /**
+             * the size of the impostor. Defaults to 10cm
+             */
+            impostorSize?: number | {
+                width: number;
+                height: number;
+                depth: number;
+            };
+            /**
+             * Friction definitions
+             */
+            friction?: number;
+            /**
+             * Restitution
+             */
+            restitution?: number;
+        };
     }
     /**
      * Add physics impostor to your webxr controllers,
@@ -72830,6 +72863,8 @@ declare module "babylonjs/XR/features/WebXRControllerPhysics" {
         private _lastTimestamp;
         private _delta;
         private _controllers;
+        private _headsetImpostor?;
+        private _headsetMesh?;
         private _tmpVector;
         private _tmpQuaternion;
         /**
@@ -72853,6 +72888,18 @@ declare module "babylonjs/XR/features/WebXRControllerPhysics" {
             restitution?: number;
         }): void;
         /**
+         * Get the physics impostor of a specific controller.
+         * The impostor is not attached to a mesh because a mesh for each controller is not obligatory
+         * @param controller the controller or the controller id of which to get the impostor
+         * @returns the impostor or null
+         */
+        getImpostorForController(controller: WebXRInputSource | string): Nullable<PhysicsImpostor>;
+        /**
+         * Get the headset impostor, if enabled
+         * @returns the impostor
+         */
+        getHeadsetImpostor(): PhysicsImpostor | undefined;
+        /**
          * attach this feature
          * Will usually be called by the features manager
          *
@@ -108328,6 +108375,8 @@ declare module BABYLON {
         cameraToUseForPointers: Nullable<Camera>;
         /** @hidden */
         readonly _isScene: boolean;
+        /** @hidden */
+        _blockEntityCollection: boolean;
         /**
          * Gets or sets a boolean that indicates if the scene must clear the render buffer before rendering a frame
          */
@@ -142296,6 +142345,35 @@ declare module BABYLON {
              */
             restitution?: number;
         };
+        /**
+         * Should the headset get its own impostor
+         */
+        enableHeadsetImpostor?: boolean;
+        /**
+         * Optional parameters for the headset impostor
+         */
+        headsetImpostorParams?: {
+            /**
+             * The type of impostor to create. Default is sphere
+             */
+            impostorType: number;
+            /**
+             * the size of the impostor. Defaults to 10cm
+             */
+            impostorSize?: number | {
+                width: number;
+                height: number;
+                depth: number;
+            };
+            /**
+             * Friction definitions
+             */
+            friction?: number;
+            /**
+             * Restitution
+             */
+            restitution?: number;
+        };
     }
     /**
      * Add physics impostor to your webxr controllers,
@@ -142316,6 +142394,8 @@ declare module BABYLON {
         private _lastTimestamp;
         private _delta;
         private _controllers;
+        private _headsetImpostor?;
+        private _headsetMesh?;
         private _tmpVector;
         private _tmpQuaternion;
         /**
@@ -142339,6 +142419,18 @@ declare module BABYLON {
             restitution?: number;
         }): void;
         /**
+         * Get the physics impostor of a specific controller.
+         * The impostor is not attached to a mesh because a mesh for each controller is not obligatory
+         * @param controller the controller or the controller id of which to get the impostor
+         * @returns the impostor or null
+         */
+        getImpostorForController(controller: WebXRInputSource | string): Nullable<PhysicsImpostor>;
+        /**
+         * Get the headset impostor, if enabled
+         * @returns the impostor
+         */
+        getHeadsetImpostor(): PhysicsImpostor | undefined;
+        /**
          * attach this feature
          * Will usually be called by the features manager
          *

File diff suppressed because it is too large
+ 9 - 9
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


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

@@ -208,7 +208,7 @@
 - Selection has gaze mode (which can be forced) and touch-screen support ([#7395](https://github.com/BabylonJS/Babylon.js/issues/7395)) ([RaananW](https://github.com/RaananW/))
 - Laser pointers can be excluded from lighting influence so that they are always visible in both WebXR and WebVR ([#7323](https://github.com/BabylonJS/Babylon.js/issues/7323)) ([RaananW](https://github.com/RaananW/))
 - Full support for the online motion controller repository ([#7323](https://github.com/BabylonJS/Babylon.js/issues/7323)) ([RaananW](https://github.com/RaananW/))
-- New feature - XR Controller physics impostor for motion controllers ([RaananW](https://github.com/RaananW/))
+- New XR feature - XR Controller physics impostor for motion controllers ([RaananW](https://github.com/RaananW/))
 - Teleportation between different ground levels in WebXR is enabled ([RaananW](https://github.com/RaananW/))
 - Utility Meshes for XR (teleportation ring, selection rays) can now be rendered using a utility layer ([#7563](https://github.com/BabylonJS/Babylon.js/issues/7563)) ([RaananW](https://github.com/RaananW/))
 

+ 0 - 1
loaders/src/OBJ/objFileLoader.ts

@@ -291,7 +291,6 @@ export class OBJFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPlugi
                     }
                 }
             });
-            container.removeAllFromScene();
             return container;
         });
     }

+ 0 - 1
loaders/src/STL/stlFileLoader.ts

@@ -137,7 +137,6 @@ export class STLFileLoader implements ISceneLoaderPlugin {
     public loadAssetContainer(scene: Scene, data: string, rootUrl: string, onError?: (message: string, exception?: any) => void): AssetContainer {
         var container = new AssetContainer(scene);
         this.importMesh(null, scene, data, rootUrl, container.meshes, null, null);
-        container.removeAllFromScene();
         return container;
     }
 

+ 0 - 1
loaders/src/glTF/glTFFileLoader.ts

@@ -594,7 +594,6 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
                 Array.prototype.push.apply(container.animationGroups, result.animationGroups);
                 Array.prototype.push.apply(container.materials, materials);
                 Array.prototype.push.apply(container.textures, textures);
-                container.removeAllFromScene();
                 return container;
             });
         });

+ 5 - 0
src/Loading/sceneLoader.ts

@@ -901,6 +901,8 @@ export class SceneLoader {
             return null;
         }
 
+        scene._blockEntityCollection = true;
+
         const fileInfo = SceneLoader._getFileInfo(rootUrl, sceneFilename);
         if (!fileInfo) {
             return null;
@@ -914,6 +916,8 @@ export class SceneLoader {
         };
 
         var errorHandler = (message: Nullable<string>, exception?: any) => {
+            scene._blockEntityCollection = false;
+
             let errorMessage = "Unable to load assets from " + fileInfo.url + (message ? ": " + message : "");
 
             if (exception && exception.message) {
@@ -940,6 +944,7 @@ export class SceneLoader {
         } : undefined;
 
         var successHandler = (assets: AssetContainer) => {
+            scene._blockEntityCollection = false;
             if (onSuccess) {
                 try {
                     onSuccess(assets);

+ 86 - 7
src/XR/features/WebXRControllerPhysics.ts

@@ -8,6 +8,7 @@ import { AbstractMesh } from "../../Meshes/abstractMesh";
 import { SphereBuilder } from "../../Meshes/Builders/sphereBuilder";
 import { WebXRFeatureName, WebXRFeaturesManager } from "../webXRFeaturesManager";
 import { Logger } from '../../Misc/logger';
+import { Nullable } from '../../types';
 
 /**
  * Options for the controller physics feature
@@ -43,6 +44,33 @@ export class IWebXRControllerPhysicsOptions {
          */
         restitution?: number;
     };
+
+    /**
+     * Should the headset get its own impostor
+     */
+    enableHeadsetImpostor?: boolean;
+
+    /**
+     * Optional parameters for the headset impostor
+     */
+    headsetImpostorParams?: {
+        /**
+         * The type of impostor to create. Default is sphere
+         */
+        impostorType: number;
+        /**
+         * the size of the impostor. Defaults to 10cm
+         */
+        impostorSize?: number | { width: number, height: number, depth: number };
+        /**
+         * Friction definitions
+         */
+        friction?: number;
+        /**
+         * Restitution
+         */
+        restitution?: number;
+    };
 }
 
 /**
@@ -71,10 +99,14 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
             impostorMesh?: AbstractMesh,
             impostor: PhysicsImpostor
             oldPos?: Vector3;
+            oldSpeed?: Vector3,
             oldRotation?: Quaternion;
         }
     } = {};
 
+    private _headsetImpostor?: PhysicsImpostor;
+    private _headsetMesh?: AbstractMesh;
+
     private _tmpVector: Vector3 = new Vector3();
     private _tmpQuaternion: Quaternion = new Quaternion();
 
@@ -108,6 +140,29 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
     }
 
     /**
+     * Get the physics impostor of a specific controller.
+     * The impostor is not attached to a mesh because a mesh for each controller is not obligatory
+     * @param controller the controller or the controller id of which to get the impostor
+     * @returns the impostor or null
+     */
+    public getImpostorForController(controller: WebXRInputSource | string): Nullable<PhysicsImpostor> {
+        let id = typeof controller === "string" ? controller : controller.uniqueId;
+        if (this._controllers[id]) {
+            return this._controllers[id].impostor;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get the headset impostor, if enabled
+     * @returns the impostor
+     */
+    public getHeadsetImpostor() {
+        return this._headsetImpostor;
+    }
+
+    /**
      * attach this feature
      * Will usually be called by the features manager
      *
@@ -129,6 +184,23 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
             this._detachController(controller.uniqueId);
         });
 
+        if (this._options.enableHeadsetImpostor) {
+            const params = this._options.headsetImpostorParams || {
+                impostorType: PhysicsImpostor.SphereImpostor,
+                restitution: 0.8,
+                impostorSize: 0.3
+            };
+            const impostorSize = params.impostorSize || 0.3;
+            this._headsetMesh = SphereBuilder.CreateSphere('headset-mesh', {
+                diameterX: typeof impostorSize === 'number' ? impostorSize : impostorSize.width,
+                diameterY: typeof impostorSize === 'number' ? impostorSize : impostorSize.height,
+                diameterZ: typeof impostorSize === 'number' ? impostorSize : impostorSize.depth
+            });
+            this._headsetMesh.rotationQuaternion = new Quaternion();
+            this._headsetMesh.isVisible = false;
+            this._headsetImpostor = new PhysicsImpostor(this._headsetMesh, params.impostorType, { mass: 0, ...params });
+        }
+
         return true;
     }
 
@@ -147,6 +219,10 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
             this._detachController(controllerId);
         });
 
+        if (this._headsetMesh) {
+            this._headsetMesh.dispose();
+        }
+
         return true;
     }
 
@@ -238,6 +314,10 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
     protected _onXRFrame(_xrFrame: any): void {
         this._delta = (this._xrSessionManager.currentTimestamp - this._lastTimestamp);
         this._lastTimestamp = this._xrSessionManager.currentTimestamp;
+        if (this._headsetMesh) {
+            this._headsetMesh.position.copyFrom(this._options.xrInput.xrCamera.position);
+            this._headsetMesh.rotationQuaternion!.copyFrom(this._options.xrInput.xrCamera.rotationQuaternion!);
+        }
         Object.keys(this._controllers).forEach((controllerId) => {
             const controllerData = this._controllers[controllerId];
             const controllerMesh = controllerData.xrController.grip || controllerData.xrController.pointer;
@@ -245,14 +325,13 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
             const comparedPosition = controllerData.oldPos || controllerData.impostorMesh!.position;
             const comparedQuaternion = controllerData.oldRotation || controllerData.impostorMesh!.rotationQuaternion!;
 
-            if (!controllerMesh.position.equalsWithEpsilon(comparedPosition)) {
-                controllerMesh.position.subtractToRef(comparedPosition, this._tmpVector);
-                this._tmpVector.scaleInPlace(this._delta);
-                controllerData.impostor.setLinearVelocity(this._tmpVector);
-                if (this._debugMode) {
-                    console.log(this._tmpVector, 'linear');
-                }
+            controllerMesh.position.subtractToRef(comparedPosition, this._tmpVector);
+            this._tmpVector.scaleInPlace(this._delta);
+            controllerData.impostor.setLinearVelocity(this._tmpVector);
+            if (this._debugMode) {
+                console.log(this._tmpVector, 'linear');
             }
+
             if (!comparedQuaternion.equalsWithEpsilon(controllerMesh.rotationQuaternion!)) {
                 // roughly based on this - https://www.gamedev.net/forums/topic/347752-quaternion-and-angular-velocity/
                 comparedQuaternion.conjugateInPlace().multiplyToRef(controllerMesh.rotationQuaternion!, this._tmpQuaternion);

+ 32 - 1
src/scene.ts

@@ -152,6 +152,9 @@ export class Scene extends AbstractScene implements IAnimatable {
     /** @hidden */
     public readonly _isScene = true;
 
+    /** @hidden */
+    public _blockEntityCollection = false;
+
     /**
      * Gets or sets a boolean that indicates if the scene must clear the render buffer before rendering a frame
      */
@@ -2038,7 +2041,9 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @param recursive if all child meshes should also be added to the scene
      */
     public addMesh(newMesh: AbstractMesh, recursive = false) {
-        this.meshes.push(newMesh);
+        if (!this._blockEntityCollection) {
+            this.meshes.push(newMesh);
+        }
 
         newMesh._resyncLightSources();
 
@@ -2374,6 +2379,9 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @param newSkeleton The skeleton to add
      */
     public addSkeleton(newSkeleton: Skeleton): void {
+        if (this._blockEntityCollection) {
+            return;
+        }
         this.skeletons.push(newSkeleton);
         this.onNewSkeletonAddedObservable.notifyObservers(newSkeleton);
     }
@@ -2383,6 +2391,9 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @param newParticleSystem The particle system to add
      */
     public addParticleSystem(newParticleSystem: IParticleSystem): void {
+        if (this._blockEntityCollection) {
+            return;
+        }
         this.particleSystems.push(newParticleSystem);
     }
 
@@ -2391,6 +2402,9 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @param newAnimation The animation to add
      */
     public addAnimation(newAnimation: Animation): void {
+        if (this._blockEntityCollection) {
+            return;
+        }
         this.animations.push(newAnimation);
     }
 
@@ -2399,6 +2413,9 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @param newAnimationGroup The animation group to add
      */
     public addAnimationGroup(newAnimationGroup: AnimationGroup): void {
+        if (this._blockEntityCollection) {
+            return;
+        }
         this.animationGroups.push(newAnimationGroup);
     }
 
@@ -2407,6 +2424,9 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @param newMultiMaterial The multi-material to add
      */
     public addMultiMaterial(newMultiMaterial: MultiMaterial): void {
+        if (this._blockEntityCollection) {
+            return;
+        }
         this.multiMaterials.push(newMultiMaterial);
     }
 
@@ -2415,6 +2435,10 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @param newMaterial The material to add
      */
     public addMaterial(newMaterial: Material): void {
+        if (this._blockEntityCollection) {
+            return;
+        }
+
         newMaterial._indexInSceneMaterialArray = this.materials.length;
         this.materials.push(newMaterial);
         this.onNewMaterialAddedObservable.notifyObservers(newMaterial);
@@ -2425,6 +2449,9 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @param newMorphTargetManager The morph target to add
      */
     public addMorphTargetManager(newMorphTargetManager: MorphTargetManager): void {
+        if (this._blockEntityCollection) {
+            return;
+        }
         this.morphTargetManagers.push(newMorphTargetManager);
     }
 
@@ -2433,6 +2460,10 @@ export class Scene extends AbstractScene implements IAnimatable {
      * @param newGeometry The geometry to add
      */
     public addGeometry(newGeometry: Geometry): void {
+        if (this._blockEntityCollection) {
+            return;
+        }
+
         if (this.geometriesByUniqueId) {
             this.geometriesByUniqueId[newGeometry.uniqueId] = this.geometries.length;
         }

+ 2 - 1
tests/validation/config.json

@@ -9,7 +9,8 @@
         {
             "title": "Sprite maps",
             "playgroundId": "#ARLADE#22",
-            "referenceImage": "sprite-maps.png"
+            "referenceImage": "sprite-maps.png",            
+            "excludeFromAutomaticTesting": true
         },              
         {
             "title": "Point light shadows",