qtmobility/examples/sensors/cubehouse/camera.cpp
changeset 4 90517678cc4f
child 5 453da2cfceef
equal deleted inserted replaced
1:2b40d63a9c3d 4:90517678cc4f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt3D module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "camera.h"
       
    43 #include <QtGui/qquaternion.h>
       
    44 #include <QtCore/qmath.h>
       
    45 
       
    46 /*!
       
    47     \class Camera
       
    48     \brief The Camera class defines the projection to apply to simulate a camera's position, orientation, and optics.
       
    49     \since 4.7
       
    50     \ingroup qt3d
       
    51     \ingroup qt3d::viewing
       
    52 
       
    53     \section1 Modelview and projection transformations
       
    54 
       
    55     A Camera instance is applied to the scene in two phases:
       
    56     modelview transformation and projection transformation.
       
    57 
       
    58     During the modelview transformation, the eye(), center(), and
       
    59     upVector() are used to generate a 4x4 transformation matrix that
       
    60     reflects the viewer's current position and orientation.
       
    61 
       
    62     During the projection transformation, the projectionType(),
       
    63     nearPlane(), farPlane(), fieldOfView(), and viewSize() are used
       
    64     to define a viewing volume as a 4x4 transformation matrix.
       
    65 
       
    66     The modelview transformation matrix is returned by modelViewMatrix().
       
    67     The projection transformation matrix is returned by projectionMatrix().
       
    68 
       
    69     \section1 Positioning and orienting the view
       
    70 
       
    71     The viewer position and orientation are defined by eye(), center(),
       
    72     and upVector().  The location of the viewer in world co-ordinates is
       
    73     given by eye(), the viewer is looking at the object of interest located
       
    74     at center(), and the upVector() specifies the direction that should
       
    75     be considered "up" with respect to the viewer.
       
    76 
       
    77     The vector from the eye() to the center() is called the "view vector",
       
    78     and the cross-product of the view vector and upVector() is called
       
    79     the "side vector".  The view vector specifies the direction the
       
    80     viewer is looking, and the side vector points off to the right of
       
    81     the viewer.
       
    82 
       
    83     It is recommended that the view vector and upVector() be at right angles
       
    84     to each other, but this is not required as long as the angle between
       
    85     them is close to 90 degrees.
       
    86 
       
    87     The most common use of view and up vectors that are not at right angles
       
    88     is to simulate a human eye at a specific height above the ground looking
       
    89     down at a lower object or up at a higher object.  In this case, the
       
    90     the view vector will not be true horizontal, but the upVector() indicating
       
    91     the human's upright stance will be true vertical.
       
    92 
       
    93     \section1 Zooming the camera image
       
    94 
       
    95     There are two ways to zoom the image seen through the camera: either
       
    96     the camera eye() position can be moved closer to the object of interest,
       
    97     or the field of view of the camera lens can be changed to make it appear
       
    98     as though the object is moving closer.
       
    99 
       
   100     Changing the eye() position changes the lighting calculation in the
       
   101     scene because the viewer is in a different position, changing the
       
   102     angle of light reflection on the object's surface.
       
   103 
       
   104     The setFieldOfView() function can be used to simulate the effect of a
       
   105     camera lens.  The smaller the fieldOfView(), the closer the object
       
   106     will appear.  The lighting calculation will be the same as for the
       
   107     unzoomed scene.
       
   108 
       
   109     If fieldOfView() is zero, then a standard perspective frustum of
       
   110     viewSize() is used to define the viewing volume.  The viewSize()
       
   111     can be adjusted with setViewSize() to zoom the view.  A smaller
       
   112     viewSize() will make the the object appear closer.
       
   113 
       
   114     The fieldOfView() or viewSize() is applied as part of the
       
   115     projectionMatrix().
       
   116 
       
   117     \section1 Rotating the viewer or object of interest
       
   118 
       
   119     Rotating a viewer in 3D space is a very delicate process.  It is very
       
   120     easy to construct the rotation incorrectly and end up in a "gimbal lock"
       
   121     state where further rotations are impossible in certain directions.
       
   122 
       
   123     To help alleviate this problem, Camera uses a quaternion-based
       
   124     approach to generate rotations.  A quaternion is a compact representation
       
   125     of a rotation in 3D space.  Rotations can be combined through quaternion
       
   126     multiplication.  More information on quaternions can be found in the
       
   127     documentation for QQuaternion.
       
   128 
       
   129     Before rotating the view, you should first decide the type
       
   130     of rotation you want to perform:
       
   131 
       
   132     \list
       
   133     \i Tilting or panning a fixed eye to reveal the scene in different
       
   134        directions and orientations.  This is equivalent to mounting a camera
       
   135        on a fixed tripod and then adjusting the direction of view and
       
   136        orientation with the tripod controls.
       
   137     \i Rotating a moving viewer about the object of interest.  This is
       
   138        equivalent to moving the viewer around the object at a fixed distance,
       
   139        but with the viewer always pointing at the object.
       
   140     \endlist
       
   141 
       
   142     In the Camera class, the first type of rotation is performed with
       
   143     rotateEye() and the second with rotateCenter().  Each of these functions
       
   144     take a quaternion argument that defines the type of rotation to perform.
       
   145 
       
   146     The tilt(), pan(), and roll() functions return values that can help with
       
   147     constructing the rotation quaternions to pass to rotateEye() and
       
   148     rotateCenter().  Tilt and pan are also known as "pitch" and "yaw" in
       
   149     flight dynamics.
       
   150 
       
   151     Three axes of rotation are used to compute the quaternions.  The tilt()
       
   152     quaternion is computed with respect to the side vector, the pan()
       
   153     quaterion is computed with respect to the upVector(), and the roll()
       
   154     quaternion is computed with respect to the view vector.
       
   155 
       
   156     The following example tilts the direction the eye() is pointing
       
   157     by 5 degrees, and then pans by 45 degrees:
       
   158 
       
   159     \code
       
   160     camera.rotateEye(camera.tilt(5));
       
   161     camera.rotateEye(camera.pan(45));
       
   162     \endcode
       
   163 
       
   164     The next example performs the two rotations in a single fluid step
       
   165     (note that the rotation to be performed first is multiplied last):
       
   166 
       
   167     \code
       
   168     camera.rotateEye(camera.pan(45) * camera.tilt(5));
       
   169     \endcode
       
   170 
       
   171     These two examples will not produce the same visual result, even though
       
   172     it looks like they might.  In the first example, the upVector() is tilted
       
   173     before the pan() quaternion is computed.  In the second example, the pan()
       
   174     quaternion is computed using the original upVector().
       
   175 
       
   176     This difference in behavior is useful in different situations.  Some
       
   177     applications may wish to perform all rotations relative to the original
       
   178     viewer orientation, and other applications may wish to perform rotations
       
   179     relative to the current viewer orientation.  These application types
       
   180     correspond to the second and first examples above.
       
   181 
       
   182     \section1 Moving the viewer or object of interest
       
   183 
       
   184     The simplest way to move the viewer or object of interest is to call
       
   185     setEye() or setCenter() respectively and supply a new position in
       
   186     world co-ordinates.  However, this can lead to non-intuitive movements
       
   187     if the viewer orientation is not aligned with the world co-ordinate axes.
       
   188 
       
   189     For example, subtracting 3 from the eye() x co-ordinate will appear to
       
   190     move the eye left 3 units if the viewer orientation is aligned with the
       
   191     world co-ordinate axes.  But it will not appear to move the eye left 3
       
   192     units in any other orientation.
       
   193 
       
   194     The translation() function can be used to construct a translation
       
   195     vector that is aligned with the viewer's current orientation.
       
   196     Movement in the x direction will move along the side vector, movement in
       
   197     the y direction will move along upVector(), and movement in the z
       
   198     direction will move along the view vector.
       
   199 
       
   200     The translation() function is useful when implementing operations such
       
   201     as "step left", "jump up", and so on where the movement should be
       
   202     interpreted relative to the viewer's current orientation, not the
       
   203     world co-ordinate axes,
       
   204 
       
   205     In other words, the following two lines of code are not equivalent
       
   206     unless the view is oriented with the world co-ordinate axes:
       
   207 
       
   208     \code
       
   209     camera.translateEye(camera.translation(x, y, z));
       
   210 
       
   211     camera.translateEye(QVector3D(x, y, z));
       
   212     \endcode
       
   213 
       
   214     The following example translates the eye() position while
       
   215     keeping the object of interest at the original center():
       
   216 
       
   217     \code
       
   218     camera.translateEye(camera.translation(x, y, z));
       
   219     \endcode
       
   220 
       
   221     The following example translates the object of interest at
       
   222     center() while keeping the eye() position fixed:
       
   223 
       
   224     \code
       
   225     camera.translateCenter(camera.translation(x, y, z));
       
   226     \endcode
       
   227 
       
   228     The following example translates both the eye() and the center()
       
   229     by the same amount, which will maintain the original view vector.
       
   230 
       
   231     \code
       
   232     QVector3D vector = camera.translation(x, y, z);
       
   233     camera.translateEye(vector);
       
   234     camera.translateCenter(vector);
       
   235     \endcode
       
   236 
       
   237     It is important that the translation vector for center() be computed
       
   238     before eye() is translated if both eye() and center() must move by the
       
   239     same amount.  The following code translates center() in the viewer
       
   240     orientation after the eye() is translated:
       
   241 
       
   242     \code
       
   243     camera.translateEye(camera.translation(x, y, z));
       
   244     camera.translateCenter(camera.translation(x, y, z));
       
   245     \endcode
       
   246 
       
   247     Translating both eye() and center() by the same amount can be used
       
   248     to simulate sliding a viewer past a scene while always looking in the
       
   249     same direction (for example, filming a scene from a moving vehicle).
       
   250     An alternative is to fix the viewer and move the scene itself:
       
   251     the negation of the translation() vector can be applied to the
       
   252     scene's modelview transformation.
       
   253 
       
   254     \section1 Motion tracking
       
   255 
       
   256     Viewing of 3D scenes can be enhanced if there is some way to track
       
   257     the motion of the viewer or the orientation of the display device.
       
   258 
       
   259     Applications can use setMotionAdjustment() to alter the position
       
   260     of the camera to account for the viewer's motion.  This indicates
       
   261     the viewer's position relative to the center of the screen.
       
   262     The motionAdjustment() vector is used to determine by how much
       
   263     the camera position should be adjusted.  The distance of the viewer
       
   264     from the screen is ignored.
       
   265 
       
   266     On handheld devices that use accelerometers to determine the
       
   267     orientation of the device, the down vector due to gravity
       
   268     can be adjusted to serve as a motion tracking vector.
       
   269 
       
   270     The output of motion tracking hardware can be very noisy,
       
   271     with minor fluctuations due to viewer twitch movements or
       
   272     environmental factors.  The application is responsible for
       
   273     cleaning up the signal and removing these fluctuations before
       
   274     setMotionAdjustment() is called.
       
   275 */
       
   276 
       
   277 class CameraPrivate
       
   278 {
       
   279 public:
       
   280     CameraPrivate();
       
   281 
       
   282     Camera::ProjectionType projectionType;
       
   283     qreal fieldOfView;
       
   284     qreal nearPlane;
       
   285     qreal farPlane;
       
   286     QSizeF viewSize;
       
   287     QSizeF minViewSize;
       
   288     int screenRotation;
       
   289     QVector3D eye;
       
   290     QVector3D upVector;
       
   291     QVector3D center;
       
   292     QVector3D viewVector;
       
   293     qreal eyeSeparation;
       
   294     QVector3D motionAdjustment;
       
   295     QQuaternion motionQuaternion;
       
   296     bool adjustForAspectRatio;
       
   297 };
       
   298 
       
   299 CameraPrivate::CameraPrivate()
       
   300     : projectionType(Camera::Perspective),
       
   301       fieldOfView(0.0f),
       
   302       nearPlane(5.0f),
       
   303       farPlane(1000.0f),
       
   304       viewSize(2.0f, 2.0f),
       
   305       minViewSize(0.0001f, 0.0001f),
       
   306       screenRotation(0),
       
   307       eye(0.0f, 0.0f, 10.0f),
       
   308       upVector(0.0f, 1.0f, 0.0f),
       
   309       center(0.0f, 0.0f, 0.0f),
       
   310       viewVector(0.0f, 0.0f, -10.0f),
       
   311       eyeSeparation(0.0f),
       
   312       motionAdjustment(0.0f, 0.0f, 1.0f),
       
   313       adjustForAspectRatio(true)
       
   314 {
       
   315 }
       
   316 
       
   317 /*!
       
   318     Constructs a Camera with the default properties and
       
   319     attaches it to \a parent.
       
   320 */
       
   321 Camera::Camera(QObject *parent)
       
   322     : QObject(parent), d_ptr(new CameraPrivate)
       
   323 {
       
   324 }
       
   325 
       
   326 /*!
       
   327     Destroys this Camera object.
       
   328 */
       
   329 Camera::~Camera()
       
   330 {
       
   331     delete d_ptr;
       
   332 }
       
   333 
       
   334 /*!
       
   335     \enum Camera::ProjectionType
       
   336     This enum defines the type of view projection to use for a Camera.
       
   337 
       
   338     \value Perspective Use a perspective view.
       
   339     \value Orthographic Use an ortographic view.
       
   340 */
       
   341 
       
   342 /*!
       
   343     \property Camera::projectionType
       
   344     \brief the projection type for this camera.  The default is Perspective.
       
   345 */
       
   346 Camera::ProjectionType Camera::projectionType() const
       
   347 {
       
   348     Q_D(const Camera);
       
   349     return d->projectionType;
       
   350 }
       
   351 
       
   352 void Camera::setProjectionType(Camera::ProjectionType value)
       
   353 {
       
   354     Q_D(Camera);
       
   355     if (d->projectionType != value) {
       
   356         d->projectionType = value;
       
   357         emit projectionChanged();
       
   358     }
       
   359 }
       
   360 
       
   361 /*!
       
   362     \property Camera::fieldOfView
       
   363     \brief the field of view in degrees for a perspective projection.
       
   364 
       
   365     The default value is zero, which indicates a standard perspective
       
   366     frustum view volume of viewSize() in size.  If the value is not
       
   367     zero, then viewSize() is ignored.
       
   368 
       
   369     This value is ignored if projectionType() is Orthographic.
       
   370 
       
   371     \sa viewSize()
       
   372 */
       
   373 qreal Camera::fieldOfView() const
       
   374 {
       
   375     Q_D(const Camera);
       
   376     return d->fieldOfView;
       
   377 }
       
   378 
       
   379 void Camera::setFieldOfView(qreal angle)
       
   380 {
       
   381     Q_D(Camera);
       
   382     if (d->fieldOfView != angle) {
       
   383         d->fieldOfView = angle;
       
   384         emit projectionChanged();
       
   385     }
       
   386 }
       
   387 
       
   388 /*!
       
   389     \property Camera::nearPlane
       
   390     \brief the distance from the eye to the near clipping plane.
       
   391     The default value is 5.
       
   392 
       
   393     \sa farPlane()
       
   394 */
       
   395 qreal Camera::nearPlane() const
       
   396 {
       
   397     Q_D(const Camera);
       
   398     return d->nearPlane;
       
   399 }
       
   400 
       
   401 void Camera::setNearPlane(qreal value)
       
   402 {
       
   403     Q_D(Camera);
       
   404     if (d->nearPlane != value) {
       
   405         d->nearPlane = value;
       
   406         emit projectionChanged();
       
   407     }
       
   408 }
       
   409 
       
   410 /*!
       
   411     \property Camera::farPlane
       
   412     \brief the distance from the eye to the far clipping plane.
       
   413     The default value is 1000.
       
   414 
       
   415     \sa nearPlane()
       
   416 */
       
   417 qreal Camera::farPlane() const
       
   418 {
       
   419     Q_D(const Camera);
       
   420     return d->farPlane;
       
   421 }
       
   422 
       
   423 void Camera::setFarPlane(qreal value)
       
   424 {
       
   425     Q_D(Camera);
       
   426     if (d->farPlane != value) {
       
   427         d->farPlane = value;
       
   428         emit projectionChanged();
       
   429     }
       
   430 }
       
   431 
       
   432 /*!
       
   433     \property Camera::viewSize
       
   434     \brief the size of the front of the projection viewing volume.
       
   435     The viewing volume is assumed to be centered on the origin.
       
   436 
       
   437     The default value is (2, 2), which indicates a viewing volume front
       
   438     from (-1, -1) to (1, 1).
       
   439 
       
   440     If the width or height of the viewing volume is negative, then the
       
   441     co-ordinates will be swapped.  For example, a size of (2, -2) will
       
   442     flip the vertical axis upside down for a viewing volume from
       
   443     (-1, 1) to (1, -1).
       
   444 
       
   445     The view size will be further adjusted by the window's aspect ratio
       
   446     when projectionMatrix() is called.  For best results, the width and
       
   447     height of the view size should be the same to define an ideal square
       
   448     viewing volume, which is then extended to the final viewing volume
       
   449     width and height based on the window's aspect ratio.
       
   450 
       
   451     \sa projectionMatrix(), minViewSize()
       
   452 */
       
   453 QSizeF Camera::viewSize() const
       
   454 {
       
   455     Q_D(const Camera);
       
   456     return d->viewSize;
       
   457 }
       
   458 
       
   459 void Camera::setViewSize(const QSizeF& size)
       
   460 {
       
   461     Q_D(Camera);
       
   462     QSizeF sz(size);
       
   463     if (sz.width() < d->minViewSize.width())
       
   464         sz.setWidth(d->minViewSize.width());
       
   465     if (sz.height() < d->minViewSize.height())
       
   466         sz.setHeight(d->minViewSize.height());
       
   467     if (d->viewSize != sz) {
       
   468         d->viewSize = sz;
       
   469         emit projectionChanged();
       
   470     }
       
   471 }
       
   472 
       
   473 /*!
       
   474     \property Camera::minViewSize
       
   475     \brief the minimum size of the front of the projection viewing volume.
       
   476 
       
   477     The minimum view size is used to clamp viewSize() when zooming
       
   478     the camera closer to an object to prevent it "passing through"
       
   479     the object and causing the scale factor to become infinite.
       
   480 
       
   481     The default value is (0.0001, 0.0001).
       
   482 
       
   483     \sa projectionMatrix(), viewSize()
       
   484 */
       
   485 QSizeF Camera::minViewSize() const
       
   486 {
       
   487     Q_D(const Camera);
       
   488     return d->minViewSize;
       
   489 }
       
   490 
       
   491 void Camera::setMinViewSize(const QSizeF& size)
       
   492 {
       
   493     Q_D(Camera);
       
   494     if (d->viewSize != size) {
       
   495         d->viewSize = size;
       
   496         emit projectionChanged();
       
   497     }
       
   498 }
       
   499 
       
   500 /*!
       
   501     \property Camera::screenRotation
       
   502     \brief the screen rotation angle in degrees.  The default
       
   503     value is 0.  If this value is 90 or 270, then the view
       
   504     will be flipped width for height.  The only supported values
       
   505     are 0, 90, 180, and 270.  The screen is rotated around the
       
   506     positive z axis.
       
   507 
       
   508     This setting is intended for simple screen rotations on handheld
       
   509     devices that can be held in either portrait or landscape orientations.
       
   510     The entire screen image is rotated so that it can be viewed in a
       
   511     different device orientation.
       
   512 
       
   513     Use rotateEye() or rotateCenter() for more complex rotations
       
   514     that are not aligned with 0, 90, 180, or 270 degrees.
       
   515 */
       
   516 int Camera::screenRotation() const
       
   517 {
       
   518     Q_D(const Camera);
       
   519     return d->screenRotation;
       
   520 }
       
   521 
       
   522 void Camera::setScreenRotation(int angle)
       
   523 {
       
   524     Q_D(Camera);
       
   525     if (d->screenRotation != angle) {
       
   526         d->screenRotation = angle;
       
   527         emit projectionChanged();
       
   528     }
       
   529 }
       
   530 
       
   531 /*!
       
   532     \property Camera::xEye
       
   533     \brief the x position of the viewer's eye.  The default value is 0.
       
   534 
       
   535     \sa eye(), translateEye(), upVector(), center(), eyeSeparation()
       
   536     \sa motionAdjustment()
       
   537 */
       
   538 qreal Camera::xEye() const
       
   539 {
       
   540     Q_D(Camera);
       
   541     return d->eye.x();
       
   542 }
       
   543 
       
   544 void Camera::setXEye(qreal value)
       
   545 {
       
   546     Q_D(Camera);
       
   547     d->eye.setX(value);
       
   548     emit viewChanged();
       
   549 }
       
   550 
       
   551 /*!
       
   552     \property Camera::yEye
       
   553     \brief the y position of the viewer's eye.  The default value is 0.
       
   554 
       
   555     \sa eye(), translateEye(), upVector(), center(), eyeSeparation()
       
   556     \sa motionAdjustment()
       
   557 */
       
   558 qreal Camera::yEye() const
       
   559 {
       
   560     Q_D(Camera);
       
   561     return d->eye.y();
       
   562 }
       
   563 
       
   564 void Camera::setYEye(qreal value)
       
   565 {
       
   566     Q_D(Camera);
       
   567     d->eye.setY(value);
       
   568     emit viewChanged();
       
   569 }
       
   570 
       
   571 /*!
       
   572     \property Camera::zEye
       
   573     \brief the z position of the viewer's eye.  The default value is 10.
       
   574 
       
   575     \sa eye(), translateEye(), upVector(), center(), eyeSeparation()
       
   576     \sa motionAdjustment()
       
   577 */
       
   578 qreal Camera::zEye() const
       
   579 {
       
   580     Q_D(Camera);
       
   581 	return d->eye.z();
       
   582 }
       
   583 
       
   584 void Camera::setZEye(qreal value)
       
   585 {
       
   586     Q_D(Camera);
       
   587 	d->eye.setZ(value);
       
   588     emit viewChanged();
       
   589 }
       
   590 
       
   591 /*!
       
   592     \property Camera::eye
       
   593     \brief the position of the viewer's eye.  The default value is (0, 0, 10).
       
   594 
       
   595     \sa translateEye(), upVector(), center(), eyeSeparation()
       
   596     \sa motionAdjustment()
       
   597 */
       
   598 QVector3D Camera::eye() const
       
   599 {
       
   600     Q_D(const Camera);
       
   601     return d->eye;
       
   602 }
       
   603 
       
   604 void Camera::setEye(const QVector3D& vertex)
       
   605 {
       
   606     Q_D(Camera);
       
   607     if (d->eye != vertex) {
       
   608         d->eye = vertex;
       
   609         d->viewVector = d->center - d->eye;
       
   610         emit viewChanged();
       
   611     }
       
   612 }
       
   613 
       
   614 /*!
       
   615     Adjusts the position of the viewer's eye by the components of \a vector.
       
   616     The final position is eye() + \a vector.
       
   617 
       
   618     \sa eye(), setEye(), translateCenter()
       
   619 */
       
   620 void Camera::translateEye(const QVector3D& vector)
       
   621 {
       
   622     Q_D(Camera);
       
   623     d->eye += vector;
       
   624     d->viewVector = d->center - d->eye;
       
   625     emit viewChanged();
       
   626 }
       
   627 
       
   628 /*!
       
   629     \property Camera::upVector
       
   630     \brief the up vector for the viewer.  The default value is (0, 1, 0).
       
   631 
       
   632     \sa eye(), center()
       
   633 */
       
   634 QVector3D Camera::upVector() const
       
   635 {
       
   636     Q_D(const Camera);
       
   637     return d->upVector;
       
   638 }
       
   639 
       
   640 void Camera::setUpVector(const QVector3D& vector)
       
   641 {
       
   642     Q_D(Camera);
       
   643     if (d->upVector != vector) {
       
   644         d->upVector = vector;
       
   645         emit viewChanged();
       
   646     }
       
   647 }
       
   648 
       
   649 /*!
       
   650     \property Camera::xCentre
       
   651     \brief the x position of the center of the view visible from the viewer's
       
   652     position.  The default value is 0.
       
   653 
       
   654     \sa eye(), translateEye(), upVector(), center(), eyeSeparation()
       
   655     \sa motionAdjustment()
       
   656 */
       
   657 qreal Camera::xCentre() const
       
   658 {
       
   659 	Q_D(Camera);
       
   660 	return d->center.x();
       
   661 }
       
   662 
       
   663 void Camera::setXCentre(qreal value)
       
   664 {
       
   665     Q_D(Camera);
       
   666 	d->center.setX(value);
       
   667     emit viewChanged();
       
   668 }
       
   669 
       
   670 /*!
       
   671     \property Camera::yCentre
       
   672     \brief the y position of the center of the view visible from the 
       
   673 	viewer's position.  The default value is 0.
       
   674 
       
   675     \sa eye(), translateEye(), upVector(), center(), eyeSeparation()
       
   676     \sa motionAdjustment()
       
   677 */
       
   678 qreal Camera::yCentre() const
       
   679 {
       
   680     Q_D(Camera);
       
   681 	return d->center.y();
       
   682 }
       
   683 
       
   684 void Camera::setYCentre(qreal value)
       
   685 {
       
   686     Q_D(Camera);
       
   687 	d->center.setY(value);
       
   688     emit viewChanged();
       
   689 }
       
   690 
       
   691 /*!
       
   692     \property Camera::zCentre
       
   693     \brief the z position of the center of the view visible from the 
       
   694 	viewer's position.  The default value is 0.
       
   695 
       
   696     \sa eye(), translateEye(), upVector(), center(), eyeSeparation()
       
   697     \sa motionAdjustment()
       
   698 */
       
   699 qreal Camera::zCentre() const
       
   700 {
       
   701     Q_D(Camera);
       
   702 	return d->center.z();
       
   703 }
       
   704 
       
   705 void Camera::setZCentre(qreal value)
       
   706 {
       
   707     Q_D(Camera);
       
   708 	d->center.setZ(value);
       
   709     emit viewChanged();
       
   710 }
       
   711 
       
   712 /*!
       
   713     \property Camera::center
       
   714     \brief the center of the view visible from the viewer's position.
       
   715     The default value is (0, 0, 0).
       
   716 
       
   717     \sa translateCenter(), eye(), upVector()
       
   718 */
       
   719 QVector3D Camera::center() const
       
   720 {
       
   721     Q_D(const Camera);
       
   722     return d->center;
       
   723 }
       
   724 
       
   725 void Camera::setCenter(const QVector3D& vertex)
       
   726 {
       
   727     Q_D(Camera);
       
   728     if (d->center != vertex) {
       
   729         d->center = vertex;
       
   730         d->viewVector = d->center - d->eye;
       
   731         emit viewChanged();
       
   732     }
       
   733 }
       
   734 
       
   735 /*!
       
   736     Adjusts the center of the view by the components of \a vector.
       
   737     The final position is center() + \a vector.
       
   738 
       
   739     \sa center(), setCenter(), translateEye()
       
   740 */
       
   741 void Camera::translateCenter(const QVector3D& vector)
       
   742 {
       
   743     Q_D(Camera);
       
   744     d->center += vector;
       
   745     d->viewVector = d->center - d->eye;
       
   746     emit viewChanged();
       
   747 }
       
   748 
       
   749 /*!
       
   750     \property Camera::eyeSeparation
       
   751     \brief the separation between the eyes when stereo viewing is in use,
       
   752     with eye() specifying the mid-point between the eyes.  The default
       
   753     value is 0.
       
   754 
       
   755     \sa eye()
       
   756 */
       
   757 qreal Camera::eyeSeparation() const
       
   758 {
       
   759     Q_D(const Camera);
       
   760     return d->eyeSeparation;
       
   761 }
       
   762 
       
   763 void Camera::setEyeSeparation(qreal value)
       
   764 {
       
   765     Q_D(Camera);
       
   766     if (d->eyeSeparation != value) {
       
   767         d->eyeSeparation = value;
       
   768         emit viewChanged();
       
   769     }
       
   770 }
       
   771 
       
   772 /*!
       
   773     \property Camera::motionAdjustment
       
   774     \brief the adjustment vector to apply to the eye() for user motion.
       
   775 
       
   776     This property is typically used to implement motion tracking.
       
   777     It is interpreted as a vector from the center of the screen to the
       
   778     current position of the viewer.  The angle between the motion
       
   779     adjustment vector and the screen center is used to adjust the
       
   780     position of the eye() when apply() is called.
       
   781 
       
   782     The default value is (0, 0, 1), which indicates a viewer
       
   783     directly in front of the center of the screen.
       
   784 
       
   785     The units for the vector are unspecified.  They could be
       
   786     meters, centimeters, or the force due to gravity in various
       
   787     directions from an accelerometer.  The angle defined
       
   788     by the vector is used to perform the adjustment, not its
       
   789     magnitude.
       
   790 
       
   791     The output of motion tracking hardware can be very noisy,
       
   792     with minor fluctuations due to viewer twitch movements or
       
   793     environmental factors.  The application is responsible for
       
   794     cleaning up the signal and removing these fluctuations before
       
   795     altering this property.
       
   796 
       
   797     \sa eye(), apply()
       
   798 */
       
   799 
       
   800 QVector3D Camera::motionAdjustment() const
       
   801 {
       
   802     Q_D(const Camera);
       
   803     return d->motionAdjustment;
       
   804 }
       
   805 
       
   806 void Camera::setMotionAdjustment(const QVector3D& vector)
       
   807 {
       
   808     Q_D(Camera);
       
   809     if (d->motionAdjustment != vector) {
       
   810         d->motionAdjustment = vector;
       
   811         if (vector.x() == 0.0f && vector.y() == 0.0f) {
       
   812             // If the vector is centered, then don't perform any rotations.
       
   813             d->motionQuaternion = QQuaternion();
       
   814         } else {
       
   815             // Determine the pan and tilt angles from the vector.
       
   816             QVector3D view = -vector.normalized();
       
   817             if (view.z() < 0.0f)
       
   818                 view = -view;
       
   819             qreal xangle = asin(view.x()) * 180.0f / M_PI;
       
   820             qreal yangle = asin(-view.y()) * 180.0f / M_PI;
       
   821 
       
   822             // Construct the pan and tilt quaternions.
       
   823             if (qFuzzyIsNull(xangle))
       
   824                 d->motionQuaternion = tilt(yangle);
       
   825             else if (qFuzzyIsNull(yangle))
       
   826                 d->motionQuaternion = pan(xangle);
       
   827             else
       
   828                 d->motionQuaternion = tilt(yangle) * pan(xangle);
       
   829         }
       
   830         emit viewChanged();
       
   831     }
       
   832 }
       
   833 
       
   834 /*!
       
   835     \property Camera::adjustForAspectRatio
       
   836     \brief the adjustment state of the aspect ratio in the viewing volume.
       
   837 
       
   838     By default, Camera adjusts the viewing volume for the aspect
       
   839     ratio of the window so that pixels appear square without the
       
   840     application needing to adjust viewSize() manually.
       
   841 
       
   842     If this property is false, then the aspect ratio adjustment is
       
   843     not performed.
       
   844 */
       
   845 
       
   846 bool Camera::adjustForAspectRatio() const
       
   847 {
       
   848     Q_D(const Camera);
       
   849     return d->adjustForAspectRatio;
       
   850 }
       
   851 
       
   852 void Camera::setAdjustForAspectRatio(bool value)
       
   853 {
       
   854     Q_D(Camera);
       
   855     if (d->adjustForAspectRatio != value) {
       
   856         d->adjustForAspectRatio = value;
       
   857         emit viewChanged();
       
   858     }
       
   859 }
       
   860 
       
   861 /*!
       
   862     Returns the quaternion corresponding to tilting the view up or
       
   863     down by \a angle degrees.  The returned quaternion can be applied to
       
   864     the eye() position with rotateEye() or to the center() position with
       
   865     rotateCenter().
       
   866 
       
   867     \sa pan(), roll(), rotateEye(), rotateCenter()
       
   868 */
       
   869 QQuaternion Camera::tilt(qreal angle) const
       
   870 {
       
   871     Q_D(const Camera);
       
   872     QVector3D side = QVector3D::crossProduct(d->viewVector, d->upVector);
       
   873     return QQuaternion::fromAxisAndAngle(side, angle);
       
   874 }
       
   875 
       
   876 /*!
       
   877     Returns the quaternion corresponding to panning the view left or
       
   878     right by \a angle degrees.  The returned quaternion can be applied to
       
   879     the eye() position with rotateEye() or to the center() position with
       
   880     rotateCenter().
       
   881 
       
   882     \sa tilt(), roll(), rotateEye(), rotateCenter()
       
   883 */
       
   884 QQuaternion Camera::pan(qreal angle) const
       
   885 {
       
   886     Q_D(const Camera);
       
   887     return QQuaternion::fromAxisAndAngle(d->upVector, angle);
       
   888 }
       
   889 
       
   890 /*!
       
   891     Returns the quaternion corresponding to rolling the view left or
       
   892     right by \a angle degrees.  The returned quaternion can be applied to
       
   893     the eye() position with rotateEye() or to the center() position with
       
   894     rotateCenter().
       
   895 
       
   896     \sa tilt(), pan(), rotateEye(), rotateCenter()
       
   897 */
       
   898 QQuaternion Camera::roll(qreal angle) const
       
   899 {
       
   900     Q_D(const Camera);
       
   901     return QQuaternion::fromAxisAndAngle(d->viewVector, angle);
       
   902 }
       
   903 
       
   904 /*!
       
   905     Rotates the orientation of the eye() according to the quaternion \a q.
       
   906     The eye() will remain in the same position, but the upVector() and
       
   907     center() may be altered by the rotation.
       
   908 
       
   909     \sa rotateCenter(), tilt(), pan(), roll()
       
   910 */
       
   911 void Camera::rotateEye(const QQuaternion& q)
       
   912 {
       
   913     Q_D(Camera);
       
   914     d->upVector = q.rotatedVector(d->upVector);
       
   915     d->viewVector = q.rotatedVector(d->viewVector);
       
   916     d->center = d->eye + d->viewVector;
       
   917     emit viewChanged();
       
   918 }
       
   919 
       
   920 /*!
       
   921     Rotates the position and orientation of the eye() around center()
       
   922     according to the quaternion \a q.  The center() will remain in the
       
   923     same position, but the upVector() and eye() may be altered by
       
   924     the rotation.
       
   925 
       
   926     \sa rotateEye(), tilt(), pan(), roll()
       
   927 */
       
   928 void Camera::rotateCenter(const QQuaternion& q)
       
   929 {
       
   930     Q_D(Camera);
       
   931     d->upVector = q.rotatedVector(d->upVector);
       
   932     d->viewVector = q.rotatedVector(d->viewVector);
       
   933     d->eye = d->center - d->viewVector;
       
   934     emit viewChanged();
       
   935 }
       
   936 
       
   937 /*!
       
   938     Returns a translation vector that can be used to adjust the eye()
       
   939     or center() by \a x units side-ways, \a y units up,
       
   940     and \a z units forwards.
       
   941 
       
   942     This function is useful when implementing operations such as
       
   943     "step left", "jump up", and so on where the movement should be
       
   944     interpreted relative to the viewer's current orientation, not the
       
   945     world co-ordinate axes,
       
   946 
       
   947     The translation vector can be applied to eye() or center() by
       
   948     calling translateEye() or translateCenter() respectively.
       
   949 
       
   950     \sa translateEye(), translateCenter()
       
   951 */
       
   952 QVector3D Camera::translation(qreal x, qreal y, qreal z) const
       
   953 {
       
   954     Q_D(const Camera);
       
   955     QVector3D vector(0.0f, 0.0f, 0.0f);
       
   956     if (x != 0.0f)
       
   957         vector += QVector3D::normal(d->viewVector, d->upVector) * x;
       
   958     if (y != 0.0f)
       
   959         vector += d->upVector.normalized() * y;
       
   960     if (z != 0.0f)
       
   961         vector += d->viewVector.normalized() * z;
       
   962     return vector;
       
   963 }
       
   964 
       
   965 /*!
       
   966     Returns the transformation matrix to apply to the projection matrix
       
   967     to present the scene as viewed from the camera position.
       
   968 
       
   969     The \a aspectRatio specifies the aspect ratio of the window the
       
   970     camera view is being displayed in.  An \a aspectRatio of 1 indicates that
       
   971     the window is square.  An \a aspectRatio greater than 1 indicates that
       
   972     the window is wider than it is high.  An \a aspectRatio less than 1
       
   973     indicates that the window is higher than it is wide.
       
   974 
       
   975     \sa apply(), modelViewMatrix()
       
   976 */
       
   977 QMatrix4x4 Camera::projectionMatrix(qreal aspectRatio) const
       
   978 {
       
   979     Q_D(const Camera);
       
   980     QMatrix4x4 m;
       
   981     if (!d->adjustForAspectRatio)
       
   982         aspectRatio = 1.0f;
       
   983     if (d->screenRotation != 0) {
       
   984         m.rotate((qreal)(d->screenRotation), 0.0f, 0.0f, 1.0f);
       
   985         if (d->screenRotation == 90 || d->screenRotation == 270) {
       
   986             if (aspectRatio != 0.0f)
       
   987                 aspectRatio = 1.0f / aspectRatio;
       
   988         }
       
   989     }
       
   990     if (d->projectionType == Perspective && d->fieldOfView != 0.0f) {
       
   991         m.perspective(d->fieldOfView, aspectRatio,
       
   992                       d->nearPlane, d->farPlane);
       
   993     } else {
       
   994         qreal halfWidth = d->viewSize.width() / 2.0f;
       
   995         qreal halfHeight = d->viewSize.height() / 2.0f;
       
   996         if (aspectRatio > 1.0f) {
       
   997             halfWidth *= aspectRatio;
       
   998         } else if (aspectRatio > 0.0f && aspectRatio < 1.0f) {
       
   999             halfHeight /= aspectRatio;
       
  1000         }
       
  1001         if (d->projectionType == Perspective) {
       
  1002             m.frustum(-halfWidth, halfWidth, -halfHeight, halfHeight,
       
  1003                       d->nearPlane, d->farPlane);
       
  1004         } else {
       
  1005             m.ortho(-halfWidth, halfWidth, -halfHeight, halfHeight,
       
  1006                     d->nearPlane, d->farPlane);
       
  1007         }
       
  1008     }
       
  1009     return m;
       
  1010 }
       
  1011 
       
  1012 /*!
       
  1013     Returns the transformation to apply to the modelview matrix
       
  1014     to present the scene as viewed from the eye() position.
       
  1015 
       
  1016     \sa apply(), projectionMatrix()
       
  1017 */
       
  1018 QMatrix4x4 Camera::modelViewMatrix() const
       
  1019 {
       
  1020     Q_D(const Camera);
       
  1021     QMatrix4x4 m;
       
  1022     if (d->motionQuaternion.isIdentity()) {
       
  1023         m.lookAt(d->eye, d->center, d->upVector);
       
  1024     } else {
       
  1025         QVector3D up = d->motionQuaternion.rotatedVector(d->upVector);
       
  1026         QVector3D view = d->motionQuaternion.rotatedVector(d->viewVector);
       
  1027         QVector3D eye = d->center - view;
       
  1028         m.lookAt(eye, d->center, up);
       
  1029     }
       
  1030     return m;
       
  1031 }
       
  1032 
       
  1033 /*!
       
  1034     \fn void Camera::projectionChanged()
       
  1035 
       
  1036     This signal is emitted when one of projectionType(), fieldOfView(),
       
  1037     nearPlane(), farPlane(), viewSize(), or screenRotation() changes,
       
  1038     indicating a modification to the optical properties of the camera
       
  1039     looking at the scene.
       
  1040 
       
  1041     \sa viewChanged()
       
  1042 */
       
  1043 
       
  1044 /*!
       
  1045     \fn void Camera::viewChanged()
       
  1046 
       
  1047     This signal is emitted when one of eye(), upVector(), or center()
       
  1048     changes, indicating a modification to the viewer's position or
       
  1049     orientation.
       
  1050 
       
  1051     \sa projectionChanged()
       
  1052 */