off center view

I have the following problem. I have an app that shows the view from the aircraft nose perspective. I show 3D scene and manipulate the camera with a simple function that uses camera.setView() when the aircraft moves.

function setCamera(lat, lon, height, direction, pitch, roll)

{

viewer.camera.setView({

destination: Cesium.Cartesian3.fromDegrees(lon, lat, height ),

orientation: {

heading: Cesium.Math.toRadians(direction), // value is 0.0 (north)

pitch: Cesium.Math.toRadians(-pitch) , // 0 - straight

roll: Cesium.Math.toRadians(-roll) // 0 - horizontal

}

});

It works fine and the aircraft nose always looks at the center of the screen as in the camera1.image

Now, the problem is that I want to hide a bit the view the camera/eye see, so the center of the screen (viewport) IS NOT where the camera/eye look at but is a bit offset. In other words, it would be like when having 2 eyes open I look at the same point and have a 120 fov. then I close left eye and see only 90 fov BUT I still look at the same point seeing 30deg to the left and 60 to the right. I visualised that in the camera2 image. The point at which I want to look is not the center of the screen and I see less to the left (and top as well in that example)

Currently I achieve that effect by rendering the full screen and then clipp the view I show on the web page (camera3 image) with the simple html setting:

@import url(Build.svs/Cesium/Widgets/widgets.css); #cesiumContainer { position: absolute; top: -33%; left: -10.35%; height:133%; width: 110.35%;

however the problem is the performance, because cesium will render in memory the full screen and the browser will show only clipped image. The bitmap that is rendered by Cesium is 50% bigger than the one I want to show and I hit performance issue as cesium is embedded into another 3D application that consumes a lot of GPU power.

So the question is how to achieve the same goal without the trick. I am not 3D expert, so I have no clue whether it is frustum related or camera related issue but I believe the goal could be achieved by rendering ONLY the required viewport.

Any help much appreciated

Marcin

I believe something I want to achieve is what is available in three.js using the following function:

camera = new THREE.PerspectiveCamera( for, aspect, near, far );
camera.setViewOffset( fullWidth, fullHeight, viewX, viewY, viewWidth, viewHeight );

wth example here: https://threejs.org/examples/webgl_multiple_canvases_grid.html

that allows multi screen rendering and would allow me to do what I want. Is is possible in Cesium ?

M.

Hi M,

I think you may be able to accomplish what you’re looking for by setting some of the following:

Gabby

Hi Gabby,

Thank you for your answer. I am aware of all those options however I could not find any documentation on how to use that specific options.

Look, at threejs the following function is self-explanatory

camera.setViewOffset( fullWidth, fullHeight, viewX, viewY, viewWidth, viewHeight );

I have the dimension of the full scene plus the exact location and size of the viewport I want to render. How to achieve the same function in Cesium is a question. I tried manipulating PersepctiveOffCenterFrustum and xOffset attrubutes of PerspectiveFrustum but no luck. Moreover I have no idea how to specify that fullWidth and fullHeight and then cut the view to specific viewport …

Any help/examples on using PersepctiveOffCenterFrustum. to achieve similar function as setViewOffset as in three.js would be much appreciated. I think it would be useful for the Cesium community, for example when someone would like to use Cesium in multiscreen scenario …

The only resource on the topic I found was the following one, however it does not explain how to use perspectiveOffCenterFrustum:

https://groups.google.com/forum/#!topic/cesium-dev/hoGEY8HHBjE

Marcin

Hi Marcin,

While looking for an example, I think what will work best for your use case is to keep the persepectiveFrustum and use an xOffset for horizontal offset or yOffset for vertical offset. An example of setting up the frustum with these parameter can be seen in our implementation of VR. We create two views, one for each eye, and then offset the perspective along the x axis slightly.

Thanks,

Gabby

Thanks Gabby, I already knew those 2 options but could not figure out how they work. Last days I experimented a bit and came to conclusion, than when using the offset, the eye point is still “looking” at the center of the viewer, however Cesium does not render the offseted area. Below an example in the SandCastle:

var viewer = new Cesium.Viewer(‘cesiumContainer’);

viewer.camera.frustum.yOffset= -(viewer.camera.frustum._offCenterFrustum.top - viewer.camera.frustum._offCenterFrustum.bottom)/2 ; // half height

viewer.camera.frustum.xOffset= -(viewer.camera.frustum._offCenterFrustum.left - viewer.camera.frustum._offCenterFrustum.right)/2 ; // half width

viewer.camera.setView({

destination: Cesium.Cartesian3.fromDegrees(11, 47, 9000),

orientation: {

heading: 0,

pitch: -Math.PI/2,

roll: 0

}

});

viewer.scene.debugShowFramesPerSecond =1;

and you can see the transparent part on top and left area.

Now, that is more less something I was looking for, i.e. with the trick to move the HTML element in which I embed cesium content, however I am not convinced it should work like that because you still render that empty area that is unnecessary. I noticed slight performance improvment when using the offset.

In three.js the setViewOffset , function cuts the scene so you could have multiple screen display, e.g.

What you want to do is definitely possible, see the Liquid Galaxy showcase for an example of using cesium on multiple screens using different, offset viewports.

For improved performance, you will definitely need to modify the frustum to properly cull the tiles you don’t want rendered. You may want to use the offset in combination with the html/css cropping. I’m not sure exactly what the solution is here, but for debugging, I suggest using the Cesium Inspector:

//Add Cesium Inspector

viewer.extend(Cesium.viewerCesiumInspectorMixin);

``

Check Terrain > Suspend LOD Updates then General > Show Frustum Planes. You can then move around the scene and “look” at the frustum and the tiles loaded.

If you’re getting that error for PerspectiveOffCenterFrustum, it must be a special use case for 2D mode.

Thanks,

Gabby

do you have example code to fulfill this feature likeLiquid Galaxy showcase?
i want only show half frustum, and this half fill the scream, but have no idea how to do it

do you find a better solution to fulfill this feature? it only hide some part of map , but not make the cutted pard fill the scream

Hi!

I am also looking for a solution here. The way I understand it, you can use the xoffset and yoffset to offset the PerspectiveFrustum to avoid rendering more than needed for each screen, but to select what goes on to which screen, we need to render the full view (across all screens) and then select with CSS that part that goes on the current screen.

@Gabby_Getz Thank you for your very helpful hints here. I haven’t found any other information source on this topic than this post. I do believe that the Liquid Galaxy is different, though, in that the screens there are not in one plane, but rather in a circle and for that use case, you just have to turn the camera to get the other screen rendered. No offset required. But for a grid of screens where the screens are all in one plane, we need to do the offset rendering.

Thanks in advance,
Best regards,
Stein :slight_smile: