ArcRotateCamera, events do not fire until render

Bear with me, I wanted to make a playground to demonstrate, but as this regards the render loop it wouldn’t really work.

We use our own custom render loop to ensure frames are not rendered when nothing changes in the scene. This is the majority of the time in our application, so it’s a good battery saver.

However, now when migrating to Babylon I have run into an issue with the ArcRotateCamera (probably all cameras). To now when to render a frame I need to know when someone has interacted with the Camera. So I listen for onViewMatrixChangedObservable (and onProjectionMatrixChangedObservable). Only these events only happens at scene.render().

The matrices only change when it renders (makes sense), but how do I listen for input to the ArcRotateCamera? How do I know that someone has interacted?

I feel like I’m in a Catch 22 :slight_smile:

1 Like

https://www.babylonjs-playground.com/#UD9LU6

Thanks nasimiasl, that example helped me in how I could build a playground with a custom render-loop.

This here illustrates my issue: I can not move the camera.

https://www.babylonjs-playground.com/#UD9LU6#10

https://www.babylonjs-playground.com/#UD9LU6#11
i recommend you to detach event and write your own control too
you can find a lot example for control custom camera in docs

That sound’s overly complicated… I mean, this should not be rocket science?

i think you most read the document before you start using because their are a lot tools and ways that help you for do complicated stuff easily
but if you don’t do that that be complicated .
the webgl + optimizing has any deep level math and when we mix science + math it can be hard in any level but your request is so easy and i just show how that initialized the better reference is BABYLONJS document

Sorry, I missed you replied with another playground. Yeah, listening for events on the scene is a good solution I guess

2 Likes

Tried your solution, but auto-rotate won’t work. It really feels like there should be an event in the camera which one can listen to to know when a render is needed.

Edit: Also the inertial movement will break. Do not do it like this, see my final post.

but those events can only be based on the fact that the camera moves which will only happen during render so yup chicken and egg :slight_smile:

I would suggest to use both the scene pointer events + a check on camera.autoRotate so that you can detect it in your case.

Implementing generically would cost a lot of cpu as animation/potential changes would require to be checked in order to render and it is usually pretty specific to a particular use case.

I think I found a sensible solution - my impression is that on each browserframe I shall call
camera.update();
This makes the camera do the cheap checks, and if a change has happened it will trigger the updated matrices.

3 Likes

Did not work… only get the event one frame late. So I only get every second frame :confused:

Could you provide a repro playground?

The camera matrix is normally updated as soon an input has changed.

Updated: https://www.babylonjs-playground.com/#UD9LU6#18
… but it does work, so I guess I must look for the answer in my own code :confused:

That’s why making a repro PG is useful :wink:

Still no good :confused:

Look at this:
https://www.babylonjs-playground.com/#UD9LU6#22

The inertia fails as the update only reacts to input. So, as soon as I release the mouse the cube comes to a grinding halt.

No, the inertia is taken into account correctly:

https://www.babylonjs-playground.com/#UD9LU6#23

The call to update will update the position/rotation if inertia is in effect.

In your playgroup

sceneNeedRender = false

is commented out, putting it back in again proves my point.

My final attempt:

https://www.babylonjs-playground.com/#UD9LU6#25

Babylon people, either I’m overlooking something or a “needsRender”-method is missing on Camera.

The above solution will only work for the ArcRotateCamera as other cameras will have other properties that might need to be detected.

Evgeni’s version use cameraDirection and cameraRotation on TargetCamera, which might be slightly better. Or not, I can’t tell.

But really, there should be a general method for this. I can’t be the only one facing this issue.

Actually there’s a bug in your PG:

https://www.babylonjs-playground.com/#UD9LU6#26

You should set sceneNeedRender = false before the call to scene.render() because the update to this variable (from onProjectionMatrixChangedObservable and onViewMatrixChangedObservable) will be done during the course of this call.

1 Like

Great! That does work! Thank you thank you!

1 Like