brianzinn / react-babylonjs

React for Babylon 3D engine
https://brianzinn.github.io/react-babylonjs/
812 stars 102 forks source link

vrExperienceHelper / webXRExperienceHelper - Hide controller models #199

Closed DefaultV closed 2 years ago

DefaultV commented 2 years ago

Hello! when setting up the vr experience helper, in combination with useXR I want to remove the controller models, not disable the controller feature. I've tried to do it via manual code as well but I've been unsuccessful.

<vrExperienceHelper
          webVROptions={{
            createDeviceOrientationCamera: false,
            floorMeshes: floor,
            useXR: true,
            controllerMeshes: false,
          }}
/>

However, the controller models are still visible in the space.

Bonus question (I will post it on Babylon forums as well): Can you replace the teleportation target mesh for webXR? It seems you can only change the material etc. The target mesh is readonly on XR.

Thanks in advance!

Tested on: Oculus Quest & Quest 2

brianzinn commented 2 years ago

I saw the forum post. I will look into this later on today - could be a prop not flowing through correctly.

brianzinn commented 2 years ago

Does that work for you setting teleportationTargetMesh? Let me know if you need any help setting that - also if you want to share how you connected WebXR maybe it is a good starting point for me to integrate it - I am still working out if is makes more sense as a hook or declarative (or both).

DefaultV commented 2 years ago

It does, I although have to do a observer call on onEnteringVRObservable Then grab the xr experience: const xr = e.xr as WebXRDefaultExperience; and then enable the feature. Here's the full solution to set the teleportation target:

e.xr.baseExperience.featuresManager.enableFeature(
          WebXRFeatureName.TELEPORTATION,
          "stable",
          {
            xrInput: e.xr.input,
            floorMeshes: floor,
            //teleportationTargetMesh: MeshBuilder.CreateBox("test", { size: 1 }),
            defaultTargetMeshOptions: {
              disableAnimation: true,
            },
            teleportationTargetMesh: MeshBuilder.CreateBox("target", {
              size: 0.1,
            }),
          }
        );

Disabling the controller meshes still seem to not pass properly as you said. It would be a shame to have to create a whole new webXRExperience just to disable the controllers.

const xr = await scene.createDefaultXRExperienceAsync({
        inputOptions: {
            doNotLoadControllerMeshes: true
        }
    });

Wish you godspeed on the quest for the missing link there!

brianzinn commented 2 years ago

You want to be able to pass a ref to teleportationTargetMesh from a declarative context or you are OK with the imperative MeshBuilder? I'll try to get some time tonight to create a Code Sandbox and then it will be easier to communicate on a solution. I'd like to start with a recipe on how to implement as a best practice and then work towards a re-usable React hook or declarative component. I was thinking the features manager would be a good declarative place to start.

edit: actually why do you need an observer on onEnteringVRObservable? the features can be enabled before entering (ie: even floor meshes can be added afterwards)?

DefaultV commented 2 years ago

Teleport mesh

I think the teleportationmesh actually makes sense to have with the imperative approach since the observer -> enable/disable feature approach seems fine.

The reason I need it on onEnteringVRObservable is because onCreated, the WebXR component is "undefined" at that point.

{onCreated} console.log(vrHelper.xr) -> undefined

{onEnteringVRObservable} console.log(vrHelper.xr) -> xrExperience

Controllers:

Disabling the controllers however, since babylon doesn't seem to have a nice approach after creating the instance, makes sense to have as declarative

brianzinn commented 2 years ago

OK - I ended up awaiting for a ref I did on an XR demo: https://github.com/brianzinn/xr-dom-overlay-react/blob/main/src/App.tsx#L47

That would at least provide the ref from declarative approach, but not render the XR buttons until that ref was made. On the other hand you could get a ref to the manager on creation and then access the feature and change the teleportation mesh.

I was thinking a declarative approach could be something like this (this is just a proposal):

 const floorMeshesRef = useRef([]); // set this somehow
 const fmRef = useRef(null);
 const boxRef = useRef(null);
  useEffect(() => {
    // we can check for both existing here and attch
  }, [fmRef, boxRef]);
  return (
  <Suspense>
    <xr mode='immersive-ar' onEntering={yourCallbackHere}>
     <features>
        <teleportationFeature floorMeshes={floorMeshesRef} teleportationTargetMesh={boxRef.current} />
     </features>
    </xr>
   </Suspense>
   <box ref={boxRef} size={1} name='teleportation-target' />
   )

This doesn't necessarily answer your question though as it looks like even imperatively it is not working out and that I need to look into to understand more.

brianzinn commented 2 years ago

hi @DefaultV did you figure this out?

DefaultV commented 2 years ago

No, I might be missing something but the controllerMeshes: false option in the vrExperienceHelper doesn't seem to work. The teleportation mesh can be overridden by enabling the teleport feature with the option for it non-declaratively.

brianzinn commented 2 years ago

sorry @DefaultV I dropped the ball here completely. Was this solved from the question in the babylon forum? Is there something that can be added here to support otherwise?

DefaultV commented 2 years ago

I think the confusion might be that there's kind of two questions/issues in one here.

  1. Teleportation controllers I currently don't see a way to disable the controllers or dispose the meshes without creating a whole new XR component, the current way to implement VR is through the vrExperienceHelper (which is deprecated and kind of hard to find information on, if my assumption is correct) and there doesn't seem to be any prop to disable the controllers.

  2. Teleportation target mesh https://forum.babylonjs.com/t/webxr-custom-teleportation-target-mesh/26880 This can be done by non-declaratively setting the teleportation feature and assigning the new mesh

That's the current status :smile:

brianzinn commented 2 years ago

Yes, the VR Experience Helper is deprecated - it's based on an old browser API.

Did you take the first question to the forum about disabling controllers? There is likely a way to overwrite that, but it may not be public. It would make a feature request if not currently available - we could try to get it in 5.0 release.

For question 2 - looks solved. I will make sure when I get time to write a declarative XR to account for some of these use cases - looks like need access to teleportationTargetMesh as a creation parameter. That will be generated automatically hopefully 😄

DefaultV commented 2 years ago

Sounds great! Question 2 is no problem really, the "workaround" is fine for now. Here's the post for question 1 on the forums: https://forum.babylonjs.com/t/webxr-disable-vr-controllers/21073/8 They also suggest making a whole new XR experience object.

brianzinn commented 2 years ago

Raanan is the one responsible for the XR stuff. It sounds like he is expecting you to make a whole new XR object. If there is a good reason you need to change it "in-session" then probably they would be willing to add it as a feature? This library is just a wrapper (except not for XR yet) - I am unable to add features to the base library from here. 😞 You could also work on a PR in babylonjs, if that is something that would interest you. Just ask in forum first if it would be accepted - I think there is a bit of a code freeze now as 5.0 is in a release candidate.

DefaultV commented 2 years ago

I think the conclusion is wait for the XR wrapper on this repo :sunglasses: Thanks for the followup!