WebXR performance on a Quest 1 when close to a mesh

Hi,

I have an odd (to me) situation that I am hoping to better understand. I have a reasonably detailed mesh with approx 320k indices, 109k faces and 57 materials. The original mesh was bigger but I have done limited dissolves etc in blender to bring it down a bit and also combined all verts using the same matrial into submeshes. So I now have 57 submeshes. All the textures are power of two and small size (biggest is 1024x1024). When I import the model I freeze the world matrix and material for each mesh and disable collision detection. Everything works fine on PC and android (Galaxy S7) but on a Quest 1 there is a large frame rate drop when I am near to the mesh. If I am far from it there is no problem at all. I am wondering why the fps drops when near the model. I first thought it must be collision detection but it isnt. Is it just the screen-space size and limited power of the Quest 1 perhaps? Or is there something else that could be going on?

I also plan on reducing the number of materials and sumeshes by combining them into a larger texture atlas because currently the model generates 57 draw calls by itself which I want to reduce. That may help significantly.

My first assumption would be that it is due to the pointer-selection feature that picks forward on each frame. Run a simple experiment - disable the pointer selection (either in the exprience helper’s options, or disable the feature directly). My bet is that the performance will be much better.

You can also connect your quest to your PC and run a performance test that will show you the reason for the long frame processing time

Thanks Raanan, I disabled pointer selection by setting disablePointerSelection:true in the options but the didn’t help. I will do remote debugging and see if that shows up anything.

Just an update: I have not been able to try remote debugging yet but I did try it on a Lenovo Mirage and it has the same issue so I suspect it must be something about the model or materials.

Progress Update: I have connected to remote debug and profiled for a few seconds. I think you might be right regarding the pointer selection. I thought I had it turned off by passing option disablePointerSelection:true when creating the experience but in the profile I can see Observable.notifyObservers takes 53ms which is composed of two tasks each taking about 26ms: WebXRControllerPointerSelection._onXRFrame and Scene.simulatePointerMove which both have a main subtask of pickWithRay so it looks like pointer selection is not disabled. I will disable it another way and recheck.

Update:
Calling featuresManager.disableFeature(BABYLON.WebXRControllerPointerSelection) after creating the experience did get rid of the WebXRControllerPointerSelection._onXRFrame and Scene.simulatePointerMove tasks and gave a much better frame rate. However, now the question is how can I have pointer selection and maintain good frame rate?

Update:
I can still use pointer selection with good frame rate if I set isPickable=false on each mesh in my model. This is ok for me as I don’t want to pick the mesh anyway. If I did want to pick the mesh then I could have a non-visible bounding root mesh and set isPickable=true on that. Anyway, all is good and now getting good frame rate on Quest 1 and Lenovo Mirage.

(I am doing these updates in case it helps someone in the future with a similar issue).

Are you saying that setting the disablePointerSelection flag to true didn’t work? That seems rather odd. Would love to investigate that, if you can reproduce this. That’s a regression.

The pointer selection is the usual suspect whenever there is a performance issue on my of my scenes. As you found out, isPickable is one solution. You can also set a different predicate in order to filter the meshes it is executed on.

No it’s all good. I found another piece of test code (that I had forgotten about) that manually turned pointer selection on after creating the experience. disablePointerSelection works as expected. Dumb user error :slight_smile:

1 Like

Phew! I went through the code 3 times to be sure :slight_smile: