Engine.resize() on html element size change

engine.resize() should be called when the canvas size has changed. I believe you are already doing that. And it does seem to work, at last from what I’m seeing. The scene is still centered. I assume you want the entire model to be displayed?

About the resize observer, there is no need to call observe on each frame, only once. This is probably hurting performance (though I’m not sure if it is a no-op if you choose to observe the same element every time). It’s a great solution, and should work the way you described. What is the issue with this approach?

Thanks to the both of you for your feedback.
The camera.targetScreenOffset is a valid solution however if possible I would like the canvas to handle the centering of the camera by using the canvas size. If there is really no other solution this could be still the way to go.

However this is what I’d like to accomplish:

The canvas would resize with a transition to a percentage 50-70% of the full width. And this would be done with a css transition property so everything transitions smoothly.

Therefore the engine.resize() would have to be constantly updated during these transitions, right? This was the reason why I was calling the resize observer within the renderloop.

When doing so I get the following:

Thanks
Pieter

Hey there @Pieter_van_Stee just checking in if you need any more help with this :grin:

Hi and thanks for getting back to me on this issue.

I would like to know how this could be done.
For now I managed to solve this by just keeping the 100% width, and sliding it to the left for 50% while the right sidepanel transitions from 0% width to 50% width.

It looks the same and works in this instance.
However like I said I’d like to know how it could be done to transition the canvas width from 100% > 50% for example with a transition over 1000ms let’s say without changing the browser window width.

Thanks!

Would something like this: Animate canvas size change | Babylon.js Playground (babylonjs.com) work for your case? :thinking:

I’m confirming that resize doesn’t work as expected. i have small canvas on the page and want to create logic when i click on it, it becomes bigger(like almost full page) i’m using resize but it does nothing. the scene is just becomes bigger without changing its resolution. the strange thing here is when i click on it again it changes(!) resolution. I wanted to create question about it later when i will try to do something with this and just saw this question

Could be a workaround, however it looks a bit less smooth than pure css.
So for now I would omit having to use this feature, but If I had to, I 'll try your suggestion.

Thanks!
Pieter

What do you mean by “changing the resolution”? It’s a bit hard to understand the expected behavior from just this description.

I gave it a try with CSS transitions and your approach to call resize on render loop: Babylon Template (carolhmj.github.io) :thinking:

Great, this would be a smooth result :+1: thanks!
Are you, and how are you triggering a re-render on each changed css width?

Thanks for this example!
Pieter

I checked again and looks like i found my problem.
My issue is that width/height of canvas is not the same as width and height of css style which has canvas.
I used style to change size of canvas. In this case block becomes bigger but width and height of canvas is not changed. when babylon resize is occured it use width and size of canvas and because they are small i get such picture (that’s what i meant it’s not changing resolution)


when such picture is expected

Looks like my solution is to change width and height of canvas not css style of it.
Thanks

1 Like

I had to go with engine.resize in the render loop function, or else the engine wouldn’t resize properly quick-demos/transition-screen-size.html at 8063dcc4d61dcd777051834fb6d537fdc05e3815 · carolhmj/quick-demos · GitHub

Ok, thanks.
Is this bad for the performance?
Would it be better to wrap this in an if statement to turn the engine.resize on/off?

Thanks

It will have some effect on performance, I tested with a few different scenes and while the transition occurred a few frames were dropped. But it wasn’t an unreasonable amount, and the only case where I saw very long frames was in a scene that was already quite heavy by itself. So I think if your scene isn’t very very heavy it will be fine. The if statement won’t be necessary as the setSize function already checks if the size has changed before running: Babylon.js/thinEngine.ts at f610f68b036265c9e0b50ddb27428c1370ec468a · BabylonJS/Babylon.js · GitHub

Hey, @Pieter_van_Stee.
I’ve read the thread and I was wondering that maybe you can get it done another way.
Instead of calling the engine.resize() maybe you can just slide the right section over the canvas and move the camera accordingly?
Eg. if the right section is 50% width of the window then you should move the camera 25% to the left.
That way you don’t need to deal with re-rendering at all.

Cheers,
Jakub

Indeed you’re right.
At the moment I have set it up like this and works perfectly in this case.
However I wanted to know for when I come across a case where I can’t cover the canvas and have to resize it. But for now I’ll keep it like this cause not having to keep resizing the scene will improve performance I guess.

Thanks for the tip!

2 Likes

Thanks, interesting to know!

1 Like

Just wanted to add we do have support for zoom-changes in your browser:

Babylon.js Playground (babylonjs.com)

When you create the engine you can set the 4th variable to be true - auto-adjust the hardware scaling ratio according to your zoom level.

4 Likes

Been having the same problem, engine.resize() seems to do nothing when called after changing the canvas size via CSS (using ReactBootstrap).

Adding engine.resize() to the render loop however, seems to fix the behavior. Aspect ratios are now preserved.

Thought it might be a race condition, like the engine resize was being calculated before the canvas size change had completed (because React may be making the change asynchronously). But even adding delays before dispatching the resize event, does nothing.

So render loop it is.

TBH I have experienced this behavior somewhere else and wanted to dig into that soon (soon is very abstract. tomorrow? 3 weeks? I sadly don’t know yet :-)).
My temporary solution was to call engine.resize() 5 times (in 5 consecutive frames) instead of once, after a resize is needed. I know it is not a solution, it is just a suggestion to save a bit of computation time in your render loop. a very naive approach would be:

let numberOfTimes = 0;
//...
// Render loop
const renderLoop = () => {
  if(numberOfTimes--) {
    engine.resize();
  }
  scene.render();
}

// on resize needed callback - 
const onResizeNeeded = () => {
  numberOfTimes =5;
}

very naive. and of course can be better…

1 Like