off center view

402 views
Skip to first unread message

websim...@gmail.com

unread,
Jan 11, 2018, 12:16:50 PM1/11/18
to cesium-dev
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:

  <style>
      @import url(Build.svs/Cesium/Widgets/widgets.css);

      #cesiumContainer {

          position: absolute;
          top: -33%;
          left: -10.35%;
          height:133%;
          width: 110.35%;

</style>

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


camera1.jpg
camera2.jpg
camera3.png

websim...@gmail.com

unread,
Jan 12, 2018, 11:27:19 AM1/12/18
to cesium-dev
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 );


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

M.

Gabby Getz

unread,
Jan 12, 2018, 1:45:33 PM1/12/18
to cesium-dev
Hi M,

I think you may be able to accomplish what you're looking for by setting some of the following:
Thanks, I hope some of that helps!
Gabby

websim...@gmail.com

unread,
Jan 15, 2018, 5:05:48 AM1/15/18
to cesium-dev
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:


Marcin

Gabby Getz

unread,
Jan 16, 2018, 10:10:26 AM1/16/18
to cesium-dev
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

websim...@gmail.com

unread,
Jan 23, 2018, 6:11:20 AM1/23/18
to cesium-dev
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.

+---+---+---+
| A | B | C |
+---+---+---+
| D | E | F |
+---+---+---+

while in Cesium your widget/viewer still needs to be full size. Any chances of fixing that ?

I also played with PerspectiveOffCenterFrustum but with no success. Even when I cloned the frustum and assigned the new frustum to the camera I hit the exception. I wonder what this object is for. 

var frustum = viewer.camera.frustum._offCenterFrustum.clone(); 
viewer.camera.frustum = frustum;

DeveloperError: A PerspectiveFrustum or OrthographicFrustum is required in 3D and Columbus view

Regards

Marcin

Gabby Getz

unread,
Jan 25, 2018, 2:13:12 PM1/25/18
to cesium-dev
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
Reply all
Reply to author
Forward
0 new messages