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