Offset viewport to pan scene in 2D

I am modifying the x and y coordinates of my camera’s viewport to reposition my scene in 2D. In my dynamic UI, sometimes the center of the scene is not aligned with the center of my window.

This strategy works pretty well, but the edges of scene are sometimes clipped. I tried adjusting the width and height of the viewport to compensate, but this can change the apparent zoom level of the scene. Not what I wanted.

Is there a better way to do what I need? Or is there a way to prevent clipping while preserving the zoom level?

Hello and welcome!

do you mind to share a simple playground that showcases your issue?

Thanks for the quick response. I will try to develop a simple playground today.

One quick observation is that working with the viewport isn’t quite as nice as other parts of Babylon. For example, I would like to animate these panning offsets, but Animation doesn’t work because a Viewport is not a Node. I had to write my own animation class, and it works quite well, but it took more effort than most things I’ve done in Babylon. There don’t seem to be many examples of Viewport use in the code samples, so I may be doing something a little off the beaten path.

You should still be able to animate the viewport somehow
A PG will definitely help :smiley:

Here is a slight modification of the starter playground that shows the clipping issue:

Thanks for looking, and for all that you do for the Babylon community. It’s an awesome library.

Ok I see
you cannot do that with viewports
I would recommend to simply create a root transformNode, make sure that all the meshes, lights and cameras are set as child of this node and then move the node :slight_smile:

Ah, that makes sense. And it fixes my animation issue too! Will it be easy to translate in screen coordinates along the horizontal and vertical axes of the camera? This might be trivial, or it might require some complicated math. I’m not sure which it is.

If I have to change the root node whenever the camera moves or the zoom level changes, it will be a challenge. If it’s trivial, I will create a playground to demonstrate the strategy.

1 Like

you can use Vector3.Project static function to project 3d coordinates to 2D
And the opposite as well with Vector3.Unproject :wink:

Here is a new version of my playground using the strategy you suggested:

I translate by 2 units along the X axis, and the result is correctly rendered. But when you rotate the camera with a horizontal mouse drag, it no longer spins around the center axis. This is different from what happens with a simple offset of the viewport.

I guess I could reimplement the mouse drag response to adjust for the changes, but it’s a lot of work. Is this the best approach?

camera has to be parented as well:

Yes, I tried parenting the camera, but if both the camera and the meshes are translated by the same amount, there is no relative motion between them, and no translation is evident in the rendered result. I think reimplementing rotation in response to mouse drags is my only fix. I hope I’m not misunderstanding something basic in your suggestion.

Or maybe it is me misunderstanding your need :slight_smile:
I though you wanted to move the entire scene

I’ll describe my scenario a little better so it will be more obvious what I’m trying to do.
I’m using Babylon to render a robot arm that we are controlling. I have a hidden side panel that the operator can slide open to access more controls. When the side panel slides open over the rendered scene, it may obscure something the operator wanted to see. As the panel opens, I want to slide the robot arm over within its fixed-size canvas so it is still visible.
When I translate the camera along with the robot arm, nothing changes in the rendered scene. If the camera doesn’t move, then the scene shifts in the canvas.
What I would really love is a Vector2 field in the camera that allows me to control the rendered position in the canvas. It would make this scenario trivial and easy to animate.

You could do this like that:… I guess :slight_smile:

Thanks for the example. Unfortunately, it still has the same clipping problem that affects all viewport translations. I modified your example slightly to translate horizontally when the button is clicked. If you try to rotate with the mouse afterwards, you will see the clipping problem on the left side of the window.
As Deltakosh said, the viewport just isn’t designed for this. Moving the whole universe seems a bit awkward to achieve a simple translation on the screen. I think it should be an offset in Camera.

Here’s the clipped output that I’m seeing…

Hey @Don_Marsh,

If I’m seeing this correctly, when the button is hit, you’re shifting the x for the camera’s viewport to the right by some amount.

So for the visual clipping, it would look something like this

So the reason for the clipped output is that there’s nothing to put in its place. If you’re trying to get something to overlay your screen like a menu or panel, using viewports, you’ll need to create another camera that points to what you want to display for your panel and either overlay it on your scene or shift the camera and put it in the empty space.

Here’s a quick PG illustrating what I mean: Simple GUI in fullscreen mode | Babylon.js Playground

Please note, the button won’t work on the main screen after pressed but will work on the other side screen to remove the “menu”.

In this example, when you click the button, a different sphere will appear and overlap the screen. If you click on the button on this new sphere, it should disappear.

Additionally, you’ll need to have both cameras in the scene.activeCameras list to render at the same time. When you no longer need your menu/panel camera, just remove it from the list.

If you uncomment lines 52 and 57, it should shift the screen as before and will take up that white space in the paint drawing above. Is this kind of what you’re going for?

1 Like

Ohhhh I finaly get what you want :slight_smile: yup you would need to move things to prevent clipping.

Thanks, @PolygonalSun. I think your suggestion might work, but introducing multiple cameras just to shift pixels in the output seems complicated. @Deltakosh’s solution is easier for me to understand, although I will have to do some complicated things to make rotation work around the original axis. Considering the simple offset I am trying to implement, every solution seems like more work than it should be.