Viadeo Twitter Google Bookmarks ! Facebook Digg del.icio.us MySpace Yahoo MyWeb Blinklist Netvouz Reddit Simpy StumbleUpon Bookmarks Windows Live Favorites 
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Classes principales  ·  Annotées  ·  Classes groupées  ·  Modules  ·  Fonctions  · 

Camera and View Frustum

The QGLCamera class provides useful viewing functionality, such as being able to position and orient view point within a scene. In combination with the QGLPainter::isCullable() function, basic view frustum culling is available. To understand in more depth these concepts, or to verify the implementation more details of these are presented here. To simply use the functionality read the documentation.

The Default Camera

Qt3D uses the OpenGL co-ordinate system, that is a right-handed system. In this system you can think of X as pointing to the right, Y as pointing up and Z as pointing toward you. If you hold your right-hand so that the thumb, index and middle fingers are all at right angles to each other, then

  • Thumb - X axis - points to the right
  • Index - Y axis - points upward
  • Middle - Z axis - points toward you

When you first create a QGLCamera object, by default it has

 QGLCamera camera;
 qDebug() camera;
 --
 // displays:
 QGLCamera
     projection: Perspective -- viewsize: 2 x 2
     near-plane: 5 -- far-plane: 1000 -- field-of-view: 0
     rotation: 0  -- motion adjust: QVector3D(0, 0, 1)  -- aspect adjust: true
     eye: QVector3D(0, 0, 10) -- center: QVector3D(0, 0, 0) -- up: QVector3D(0, 1, 0)

In the visualisation just mentioned, with positive Z pointing toward you the camera is sitting at the tip of your middle finger, looking in the same direction you are, that is down toward the negative end of the Z axis.

Positioning a Custom Camera.

In this image we have a camera positioned with the following settings:

 camera.setNearPlane(2.2f);
 camera.setFarPlane(14.0f);
 camera.setViewSize(QSizeF(1.257f, 1.257f));
 camera.setEye(QVector3D(0, 0, -8.0f));

This screen capture from a 3D modelling program shows how this camera is set up in a scene, where its viewing a cube. The image shows a purple area which indicates the view frustum, which you can think of for now as the area captured by the camera. Actually its more correct to think of the volume captured by the camera, and imagine that the purple indication in the image is the shadow cast by this volume.

[Missing image view-frustum-angle-shot.png]

The odd value for view size comes from the far plane size which was set at 8 x 8 when creating the diagram: by similar triangles (8 / 14) x 2.2 = 1.257. There is no API call for setting the size of the far-plane, same as in OpenGL. So to get this 8 x 8 far plane we had to work out the near plane size.

[Missing image view-frustum-origin.png]

This plan view shows the parameters of the camera by reference to a grid. You can see that the camera is situated - by QGLCamera::setEye() - to a point 8 units back along the negative z axis. The far plane is 14 units away from the eye - set by QGLCamera::setFarPlane().

Note that here also the camera is sitting down the negative z axis, looking back toward us - the opposite of the default. Its near plane and far plane are also much closer. The camera is still pointing to the origin - where a 3D cube is situated, ready to be viewed by the camera.

The View Frustum

The camera can only see a part of the scene - not all of it. Anything too far to the camera's right or left is out of the range of its view, and even though that part of the scene may contain geometry that is sent to the GPU for processing, those triangles will not be visible on the screen. The GPU will clip them away - but it still has to do work to do this.

The part of the scene which the camera can see, and which will get displayed is called the View Frustum. A Frustum is a geometric shape, like a pyramid with its top cut off. It has sloping sides due to the perspective transformation performed by OpenGL, when simulating the effect of the camera in the 3D scene.

The cube in this scene has 6 sides, just like the view frustum, so we can compare the names of these:

CubeView Frustum
FrontNear Plane
BackFar Plane
Left sideLeft side
Right sideRight side
TopTop
BottomBottom

Like the cube, the frustum is a solid, and can contain things. You can think of it as having a set of bounds. Anything inside these bounds is rendered by OpenGL.

[Missing image view-frustum-10-degrees-angle-shot.png]

In this image, we see the camera as a black-line wire-frame. The rectangle of the front of the camera represents the aperture.

The triangular purple colored area on the floor corresponds to the camera's eye and spreads out, as determined by the size of the camera's aperture. If you extended the lines from the camera's eye to the four corners of its aperture, those lines would define the view frustum. That view frustum would be the same size as the purple view triangle, except the part behind the camera aperture is sliced off.

Anything that falls inside the black wire-frame of the camera itself does not get displayed.

Because the scene needs to be projected onto a camera aperture of a non-zero size, this means there is this area between the eye of the camera and its aperture which cannot be displayed. Notice that the camera aperture and the Near Plane of the view frustum are the same thing.

We can also say that anything which falls outside the fiew frustum does not get displayed including anything in front of the near plane. Poor camera positioning in a scene can often result in this near plane culling which can produce odd visual effects as geometry appears and disappears when it passes in front and behind of the near plane.

View Frustum Culling

Carefully examine the next 3 screenshots, which show the same plan view of the camera, cube and view - except the cube is rotated arount the eye of the camera by 10 degrees each time.

[Missing image view-frustum-10-degrees.png]

In this image the cube is slightly out of the view frustum. It still must be sent to the GPU, but some of its pixels will be clipped off during rendering.

[Missing image view-frustum-20-degrees.png]

In this image the cube is mostly out of the view frustum. It still must be sent to the GPU, but most of its pixels will be clipped off during rendering.

[Missing image view-frustum-30-degrees.png]

In this image the cube is completey out of the view frustum. Performance could be improved by not sending the cubes geometry to the GPU at all. This test must be made on the CPU side, so therefore it must be very cheap to do in order to beat the cost of just sending it anyway and allowing the GPU to clip away all of it.

The optimisation technique where you detect this case is called View Frustum Culling and it can a simple and valuable performance enhancement. Qt3D implements view frustum culling via the QGLPainter::isCullable() function.

Aspect-Ratio Correction

The default camera has a viewport which is 2 x 2 in size, as discussed above. However when the camera is used to display a scene on a QGLAbstractSurface, for example a QGLWidgetSurface, the aspect ratio of that surface is taken into account in the View Frustum. Specifically code in the QGLCamera::projectionMatrix() function takes the aspect ratio and expands the default viewport to match. If the surface is wider than it is high, the aspect ratio is greater than 1 and the viewport width is multiplied by the aspect ratio to make it larger. If the surface is higher than it is wide, the aspect ratio is less than 1 and the viewport height is divided by the aspect ratio to make it larger. The result is the viewport aspect ratio matches that of the surface it is to be displayed on.

 QGLWidget widget;              // creates a 640 x 480 widget by default
 QGLPainter painter(&widget)    // internally makes a 640 x 480 QGLWidgetSurface
 qreal asp = painter.currentSurface()->aspectRatio();
 // asp == 1.3333 which is (640 / 480)
 QGLCamera camera;              // default camera as above
 painter.setCamera(&camera);    // applies the aspect ratio to the perspective projection
 QMatrix4x4 p = painter.projectionMatrix().top();
 QMatrix4x4 q;
 q.frustum(-asp, asp, -1, 1, camera.nearPlane(), camera.farPlane());
 qDebug() << q == p;                     // prints "true"

One result of this is that clipping to the view frustum can only be done with the knowledge of the surface because more of the scene is visible to the left and right than would be suggested by the default camera settings.

Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt 5.0-snapshot
Copyright © 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur ? Un bug ? Une redirection cassée ? Ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
 
 
 
 
Partenaires

Hébergement Web