# Questions about onPointerObservable

**URL:** <https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330>\
**Category:** Questions\
**Tags:** pointerevents\
**Created:** [December 12, 2024, 4:55pm UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330 "2024-12-12T16:55:09Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![hsonguk](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/hsonguk/32/37238_2.png) [@hsonguk](https://forum.babylonjs.com/u/hsonguk)\
**Post date:** [December 12, 2024, 4:55pm UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330/1 "2024-12-12T16:55:09Z")

</div>

Dear experts, recently i am analyzing the performance bottleneck of the 3D viewer.

One of the issue i met is related to the mouse event onPointerObservable.

In the project, we used ArcRotateCamera and zoomToMouseLocation=true.

Based on my understanding, zoomtomouse will not actually calculate what the camera direction hit but with fixed radius. In some cases it is fine, however, when zooming in closer to the terrain, it is very difficult to move the view further.

So we introduced the onPointerObservable event and update the target and radius according to what is hit by the camera ray in POINTERWHEEL event. The overall logic works well. Then we hit the issue of performance when there is large mesh present in the scenario (e.g. terrain mesh).

The FPS will drop from 50 to 20-30fps whenever I zoom in/out or even pan the scene. It seems by default, the pickByRay will always be fired.

I will try the new GPUPick in onPointerObservable, my question is if it will improve the performance in my scenario? I am a bit confused with the workflow behind the onPointerObservable. When using GPUPick, will it still firstly calculate pickinfo under POINTERWHEEL event?

Or is there any better way to meet the original requirement?

Many thanks for your help. --Hui

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [December 13, 2024, 12:10am UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330/2 "2024-12-13T00:10:29Z")

</div>



---

<div class="post-metadata">

**Author:** ![hsonguk](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/hsonguk/32/37238_2.png) [@hsonguk](https://forum.babylonjs.com/u/hsonguk)\
**Post date:** [December 13, 2024, 11:40am UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330/3 "2024-12-13T11:40:57Z")

</div>

This morning I am trying to create a PG for that.

And the issue that i find is a bit different now.

[Mouse Event Test | Babylon.js Playground](https://playground.babylonjs.com/#ZIMM04#1)

I have try to load the terrain mesh in different coordinates method (one with node transform and uniformed vertices and the other with its absolute coordinates which are all very large). Other than that, they have exactly the same number of vertices and faces.

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/0/9/09829711ff91244d71c473729421b07979c555fb.png)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/3/f/3f7c1c81f104cd22ccfe0a9bf0302eba0671ed01.png)

They all trigger ray hit test, but the performance is significantly different.

Is there any root cause behind these results? Does it mean that I need to always uniform the mesh coordinates?

Many Thanks.

---

<div class="post-metadata">

**Author:** ![hsonguk](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/hsonguk/32/37238_2.png) [@hsonguk](https://forum.babylonjs.com/u/hsonguk)\
**Post date:** [December 13, 2024, 12:22pm UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330/4 "2024-12-13T12:22:56Z")

</div>

Sorry need to update what i find again.

I have now convert the original glb to same un-uniformed form using “glTFPack” tool.

I have compared the two glb files, i cannot tell any difference between the two now.

But their mouse event (rotate by left click or pan by right click) performance is still with big difference.

[Mouse Event Test | Babylon.js Playground](https://playground.babylonjs.com/#ZIMM04#3)

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/f/c/fc451adf4dbf027707d2ed1cd40dfcd5070e3f09.png)

Can anyone help to explain the root cause?

Many thanks.

---

<div class="post-metadata">

**Author:** ![Deltakosh](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/deltakosh/32/26635_2.png) [@Deltakosh](https://forum.babylonjs.com/u/Deltakosh)\
**Post date:** [December 13, 2024, 5:24pm UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330/5 "2024-12-13T17:24:43Z")

</div>

cc @ryantrem

---

<div class="post-metadata">

**Author:** ![Deltakosh](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/deltakosh/32/26635_2.png) [@Deltakosh](https://forum.babylonjs.com/u/Deltakosh)\
**Post date:** [December 13, 2024, 5:25pm UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330/6 "2024-12-13T17:25:12Z")

</div>

Also adding @amoebachant for the input management

---

<div class="post-metadata">

**Author:** ![ryantrem](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/ryantrem/32/34010_2.png) [@ryantrem](https://forum.babylonjs.com/u/ryantrem)\
**Post date:** [December 13, 2024, 8:26pm UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330/7 "2024-12-13T20:26:20Z")

</div>

> [@hsonguk](#):
>
> the performance bottleneck of the 3D viewer

Just to be clear, “the 3D viewer” in this context is something you have created yourself, not the [Babylon Viewer](https://doc.babylonjs.com/features/featuresDeepDive/babylonViewer/), correct?

> [@hsonguk](#):
>
> In the project, we used ArcRotateCamera and zoomToMouseLocation=true

I think in your case this will be somewhat slow, because this causes a ray cast every time the mouse wheel changes, and your model has a lot of indices/faces.

> [@hsonguk](#):
>
> I will try the new GPUPick in onPointerObservable, my question is if it will improve the performance in my scenario? I am a bit confused with the workflow behind the onPointerObservable. When using GPUPick, will it still firstly calculate pickinfo under POINTERWHEEL event?

I believe they are independent, so if you wanted to use gpu picking instead of regular picking, you would need to disable regular picking. That said, as far as I know the gpu picker only tells you the hit mesh, not the triangle that was hit, so if I’m understanding your scenario correctly, I don’t think it would give you enough info.

> [@hsonguk](#):
>
> But their mouse event (rotate by left click or pan by right click) performance is still with big difference.

In general, you may need to skip some ray casting on pointer events if you haven’t already. For example, setting `scene.skipPointerMovePicking`, `scene.skipPointerDownPicking`, etc. For your scenario, you may also be able to set `scene.pointer*FastCheck`. This will basically make ray casting return the first triangle it hits rather than the closest, but since your model is mostly flat, this might work just fine.

Depending on your needs, you might be able to use the actual Babylon Viewer as well. Here is an example:

https://codepen.io/BabylonJS/embed/preview/MYgbJMW?default-tabs=html%2Cresult&height=300&host=https%3A%2F%2Fcodepen.io&slug-hash=MYgbJMW

As far as performance being different between the two models, I don’t have an answer yet. I did some profiling and saw that the same number of faces are being tested in the ray cast, but it’s slower on one model than the other (specifically it seems to be a `Vector.subtractToRef`, which so far doesn’t make any sense). I’ll see if I can find any more answers on this one.

---

<div class="post-metadata">

**Author:** ![Deltakosh](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/deltakosh/32/26635_2.png) [@Deltakosh](https://forum.babylonjs.com/u/Deltakosh)\
**Post date:** [December 14, 2024, 7:10pm UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330/8 "2024-12-14T19:10:04Z")

</div>

To give you some updates, we have isolated the issue and it seems to look like a bug in the compiler. Somehow in one case the vector3 class is deoptimized for a reason we are not aware of yet.

We will keep this thread updated as soon as we know more

---

<div class="post-metadata">

**Author:** ![hsonguk](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/hsonguk/32/37238_2.png) [@hsonguk](https://forum.babylonjs.com/u/hsonguk)\
**Post date:** [December 17, 2024, 9:46am UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330/9 "2024-12-17T09:46:58Z")

</div>

Sorry was travelling in the past days.

> [@ryantrem](#):
>
> > [@hsonguk](#):
> >
> > the performance bottleneck of the 3D viewer
> 
> Just to be clear, “the 3D viewer” in this context is something you have created yourself, not the [Babylon Viewer](https://doc.babylonjs.com/features/featuresDeepDive/babylonViewer/), correct?
> 
> **Yes, it is a custom built 3d viewer based on BabylonJS.**
> 
> > [@hsonguk](#):
> >
> > In the project, we used ArcRotateCamera and zoomToMouseLocation=true
> 
> I think in your case this will be somewhat slow, because this causes a ray cast every time the mouse wheel changes, and your model has a lot of indices/faces.
> 
> **I am not sure about the performance, specifically, i observe the same level of complexity mesh, but with dramatic difference in performance. For one of the same terrain, it can always constantly maintain at around 50fps, then it is not really a issue I need to tackle at this stage. While the other drops to 10-20fps, then it becomes really an issue. Thus am confused what/where should be optimised.**
> 
> > [@hsonguk](#):
> >
> > I will try the new GPUPick in onPointerObservable, my question is if it will improve the performance in my scenario? I am a bit confused with the workflow behind the onPointerObservable. When using GPUPick, will it still firstly calculate pickinfo under POINTERWHEEL event?
> 
> I believe they are independent, so if you wanted to use gpu picking instead of regular picking, you would need to disable regular picking. That said, as far as I know the gpu picker only tells you the hit mesh, not the triangle that was hit, so if I’m understanding your scenario correctly, I don’t think it would give you enough info.
> 
> **Yes. It seems the GPUPickInfo is based on a different pickinfo class that does not come with the exact hit position. It may be helpful to include that position information as well. But it seems it is not relevant to this question. I guess the ray hit test by CPU will always be fired when point pick event is triggered.**
> 
> > [@hsonguk](#):
> >
> > But their mouse event (rotate by left click or pan by right click) performance is still with big difference.
> 
> In general, you may need to skip some ray casting on pointer events if you haven’t already. For example, setting `scene.skipPointerMovePicking`, `scene.skipPointerDownPicking`, etc. For your scenario, you may also be able to set `scene.pointer*FastCheck`. This will basically make ray casting return the first triangle it hits rather than the closest, but since your model is mostly flat, this might work just fine.
> 
> Depending on your needs, you might be able to use the actual Babylon Viewer as well. Here is an example:
> 
> [https://codepen.io/BabylonJS/pen/MYgbJMW](https://codepen.io/BabylonJS/pen/MYgbJMW)
> 
> **Thanks. I will try out these setting combinations and compare the performance. I will try out Babylon Viewer as well.**
> 
> As far as performance being different between the two models, I don’t have an answer yet. I did some profiling and saw that the same number of faces are being tested in the ray cast, but it’s slower on one model than the other (specifically it seems to be a `Vector.subtractToRef`, which so far doesn’t make any sense). I’ll see if I can find any more answers on this one.

**That is in fact the most confusing part. It seems that both mesh have the same level of complexity but the performance is different. One the factor is cleared with forum’s help, I may be able the prepare the mesh data in better form.**

---

<div class="post-metadata">

**Author:** ![hsonguk](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/hsonguk/32/37238_2.png) [@hsonguk](https://forum.babylonjs.com/u/hsonguk)\
**Post date:** [December 17, 2024, 9:51am UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330/10 "2024-12-17T09:51:12Z")

</div>

Thank you @Deltakosh and @ryantrem for your updates.

---

<div class="post-metadata">

**Author:** ![Deltakosh](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/deltakosh/32/26635_2.png) [@Deltakosh](https://forum.babylonjs.com/u/Deltakosh)\
**Post date:** [December 17, 2024, 4:59pm UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330/11 "2024-12-17T16:59:01Z")

</div>

We finally have the explanation!!

The slow version is slow because with more than 1 million faces the memory cache is not as efficient as the other version.  
Why? Because the slow version has faces dispatched in a random order where the fast version has faces gathered if they share common vertices.

To get rid of that we have introduce a new feature on mesh:

```auto
const terrain = scene.getMeshByName("Terrain");
await terrain.optimizeIndicesAsync();

```

That function will reorganize the indices to maximize cache hit.

PR: [Add a new optimizeIndices features to improve cache hit on large models by deltakosh · Pull Request #16009 · BabylonJS/Babylon.js](https://github.com/BabylonJS/Babylon.js/pull/16009)

---

<div class="post-metadata">

**Author:** ![hsonguk](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/hsonguk/32/37238_2.png) [@hsonguk](https://forum.babylonjs.com/u/hsonguk)\
**Post date:** [December 17, 2024, 5:58pm UTC](https://forum.babylonjs.com/t/questions-about-onpointerobservable/55330/12 "2024-12-17T17:58:02Z")

</div>

Thanks @Deltakosh as always. It explains the root cause behind, I will check if we can prepare the data with ordered face indices when generating the terrain.

Thanks @ryantrem, the PointerPickingConfiguration also helps to avoid some unnecessary ray hit test.

With the combination of two, the performance of terrain navigation is greatly improved. Truly saved my day. 🙂
