cugl.h

Go to the documentation of this file.
00001 #ifndef CUGL_H
00002 #define CUGL_H
00003 
00004 /** \file cugl.h
00005  *  Concordia University Graphics Library
00006  *
00007  * \authors Peter Grogono
00008 */
00009 
00010 /** \mainpage   Introduction
00011 
00012    The \c operator<< overloads for classes Point, Quaternion, and Matrix
00013    use the current settings of format parameters.  \c setw() determines
00014    the width of each number rather than the entire field width.
00015 
00016    Most of the classes do not have copy constructors or \c operator= overloads
00017    because the default versions generated by the compiler do the right
00018    thing (for once).  (Class PixelMap is an exception, because it has
00019    pointer members.)
00020 
00021    \c GLfloat is used as the representation type for most floating-point values.
00022    This is for compatibility with OpenGL.  Although OpenGL provides a choice of
00023    precision for vertex and normal data, matrices are provided in \c GLfloat form only.
00024    Single-precision floating-point provides only about six decimal places, but this
00025    is sufficient for most graphics calculations.  If the number of points, vectors,
00026    or matrices used is large, substantial amounts of memory may be saved.
00027 
00028    Acknowledgements:  Mark Kilgard, Ken Shoemake, F.S. Hill, and others, for
00029    various publications on mthematical techniques for graphics and OpenGL, and to
00030    Liping Ye for improving various features, especially bitmaps.
00031 */
00032 
00033 #include <GL/glu.h>
00034 #include <iostream>
00035 #include <math.h>
00036 
00037 namespace cugl
00038 {
00039 
00040     /**
00041      * Indicates version and last compile date.
00042      */
00043     const char version[] = "CUGL V1 2003.12.25";
00044 
00045     /**
00046      * A well-known mathematical constant.
00047      */
00048     const double PI = 4 * atan(1.0);
00049 
00050     /**
00051      * The type of OpenGL projection and model view matrices.
00052      */
00053     typedef GLfloat GL_Matrix[4][4];
00054 
00055     /**
00056      * \defgroup errors Error messages
00057      */
00058 
00059     //@{
00060 
00061     /**
00062      * Enumeration values for CUGL function errors.
00063      */
00064     enum CUGLErrorType
00065     {
00066         NO_ERROR = 0,           /**< No error has occurred since the error flag was reset. */
00067         BAD_INDEX,              /**< Encountered an invalid array index. */
00068         BAD_MATRIX_MODE,        /**< The matrix mode was not GL_PROJECTION or GL_MODELVIEW. */
00069         BAD_ROTATION_MATRIX,    /**< The given matrix was not a rotation matrix. */
00070         SINGULAR_MATRIX,        /**< The matrix is singular. */
00071         ZERO_DIVISOR,           /**< An attempt was made to divide by zero. */
00072         ZERO_NORM,              /**< An attempt was made to normalize a null vector. */
00073         BAD_INTERPOLATOR_ARG,   /**< The angle between the rotations of the interpolator is zero.  */
00074         OPEN_FAILED,            /**< The program failed to open a BMP file. */
00075         NOT_BMP_FILE,           /**< The file opened was not a BMP file. */
00076         NOT_24_BITS,            /**< The BMP file was not in 24-bit format. */
00077         COMPRESSED_BMP_FILE,    /**< The BMP file was in compressed form. */
00078         NOT_ENOUGH_MEMORY,      /**< There is not enough memory to store the pixel map. */
00079         NO_PIX_MAP,             /**< There is no pixel map to draw. */
00080         BAD_PLANE,              /**< Parameters do not define a plane. */
00081         BAD_LINE,               /**< The line lies in the plane. */
00082         TOO_MANY_MATERIALS,     /**< Too many materials. */
00083         TOO_MANY_POINTS         /**< Too many points. */
00084     };
00085 
00086     /**
00087      * Set code to \c NO_ERROR and return last error code.
00088      * \return the most recent error code;
00089      */
00090     CUGLErrorType getError();
00091 
00092     /**
00093      * Return a message describing an error.
00094      */
00095     const char *getErrorString(CUGLErrorType err);
00096 
00097     /**
00098      * Display a message if an CUGL error has occurred.
00099      * This function checks the CUGL error status.
00100      * If no error has occurred, it has no effect.
00101      * If CUGL has reported an error, this function writes
00102      * the CUGL error code and the corresponding message
00103      * to the stream \c cerr.
00104      *
00105      * Since \c getError() clears the CUGL error flag,
00106      * after calling this function CUGL shows no errors.
00107      *
00108      * This function is intended mainly for development and
00109      * should not normally be included in a production program.
00110      */
00111     void checkCUGLStatus();
00112 
00113     /**
00114      * Display a message if an OpenGL error has occurred.
00115      * This function checks the OpenGL error status.
00116      * If no error has occurred, it has no effect.
00117      * If OpenGL has reported an error, this function writes
00118      * the OpenGL error code and the corresponding message
00119      * to the stream \c cerr.
00120      *
00121      * Since \c glGetError() clears the OpenGL error flag,
00122      * after calling this function OpenGL shows no errors.
00123      *
00124      * This function is intended mainly for development and
00125      * should not normally be included in a production program.
00126      */
00127     void checkOpenGLStatus();
00128 
00129     // End of error messages
00130     //@}
00131 
00132     // Forward declarations.
00133     class Vector;
00134     class Quaternion;
00135 
00136     /**
00137      * An instance is a point represented by four homogeneous coordinates.
00138      * A point is represented by \a (x,y,z,w) in which each component is a \c GLfloat.
00139      * If \a w=0, the point is `at infinity'.  Points at infinity may be used like other
00140      * points, but a few operations do not work for them.  CUGL functions do not issue an
00141      * error message when this happens: they simply return a default result.
00142      *
00143      * A Point is in normal form if \a w=1.  A Point may be normalized if \a w!=0.
00144      */
00145     class Point
00146     {
00147     public:
00148         friend class Line;
00149         friend class Vector;
00150         friend class Matrix;
00151         friend class Plane;
00152 
00153         /**
00154          * Construct a point with coordinates (x, y, z, w).
00155          * Default parameter values: (0,0,0,1).
00156          */
00157         Point(GLfloat x = 0, GLfloat y = 0, GLfloat z = 0, GLfloat w = 1);
00158 
00159         /**
00160          * Construct a point from the array \c coordinates.
00161          * \pre The array must have at least four components.
00162          */
00163         Point (GLfloat coordinates[]);
00164 
00165         /**
00166          * Convert a Quaternion to a Point.
00167          * \note This is a rather peculiar operation and should not normally be used.
00168          * It is intended for experiments with non-linear transformations.
00169          */
00170         Point (const Quaternion & q);
00171 
00172         /**
00173          * Access coordinates: p[0] = x, p[1] = y, p[2] = z, p[3] = w.
00174          * Error BAD_INDEX reported if \c i is not one of {0,1,2, 3}.
00175          */
00176         GLfloat & operator[](int i);
00177 
00178         /**
00179          * Access coordinates: p[0] = x, p[1] = y, p[2] = z, p[3] = w.
00180          * This form is used with \c const instances (\c p[i] cannot appear on the left of \c =).
00181          * Error BAD_INDEX reported if \c i is not one of {0,1,2, 3}.
00182          */
00183         const GLfloat & operator[](int i) const;
00184 
00185         /**
00186          * Normalize this point.
00187          * A Point is in normal form if \a w=1.
00188          * Error ZERO_DIVISOR reported if \a w=0.
00189          * \note The value of this Point is changed by this function.
00190          */
00191         void normalize();
00192 
00193         /**
00194          * Return this Point in normalized form.
00195          * A Point is in normal form if \a w=1.
00196          * Error ZERO_DIVISOR reported if \a w=0.
00197          */
00198         Point unit() const;
00199 
00200         /**
00201          * Draw the point using \c glVertex4f().
00202          */
00203         void draw() const;
00204 
00205         /**
00206          * Use this point as a light position.
00207          * If w = 0, the light is directional, otherwise it is positional.
00208          * \param lightNum specifies which light to use:
00209          * it must be one of \a GL_LIGHT0, \a GL_LIGHT1, ...
00210          */
00211         void light(GLenum lightNum) const;
00212 
00213         /**
00214          * Translate to the point using \c glTranslatef().
00215          * \note If the point is at infinity (w = 0), this function has no effect.
00216          */
00217         void translate() const;
00218 
00219         /**
00220          * Scale a Point.
00221          * Scale the coordinates of a Point by dividing by the scalar \a s.
00222          * This is implemented by multiplying the \a w component of the Point
00223          * by \a s.  If \a s=0, the result is a Point at infinity.
00224          * \return the Point at \a (x,y,z,s*w).
00225          */
00226         Point operator/(GLfloat s) const;
00227 
00228         /**
00229          * Displace a Point with a Vector
00230          * \return Point at (x-w*v.x, y-w*v.y, z-w*v.z, w).
00231          */
00232         Point operator+=(const Vector & v);
00233 
00234         /**
00235          * Displace a Point with a Vector
00236          * \return Point at (x+w*v.x, y+w*v.y, z+w*v.z, w).
00237          */
00238         Point operator-=(const Vector & v);
00239 
00240         /**
00241          * Displace a Point with a Vector.
00242          * \return Point at (p.x+p.w*v.x, p.y+p.w*v.y, p.z+p.w*v.z, p.w).
00243          */
00244         friend Point operator+(const Vector & v, const Point & p);
00245 
00246         /**
00247          * Displace a Point with a Vector.
00248          * \return Point at (p.x+p.w*v.x, p.y+p.w*v.y, p.z+p.w*v.z, p.w).
00249          */
00250         friend Point operator+(const Point & p, const Vector & v);
00251 
00252         /**
00253          * Scale a point.
00254          * \return Point at (p.x + p.w*v.x, p.y + p.w*v.y, p.z + p.w*v.z).
00255          */
00256         friend Point operator*(const Point & p, GLfloat s);
00257 
00258         /**
00259          * Scale a point.
00260          * \return Point at (p.x + p.w*v.x, p.y + p.w*v.y, p.z + p.w*v.z).
00261          */
00262         friend Point operator*(GLfloat s, const Point & p);
00263 
00264         /**
00265          * Return the vector corresponding to the displacement between the two points.
00266          * This is the vector (\c p.x/p.w - \c q.x/q.w, \c p.y/p.w - \c q.y/q.w, \c p.z/p.w - \c q.z/q.w).
00267          * If \c p or \c q is a point at infinity, return the zero vector.
00268          * \return the Vector corresponding to the displacement between the two points.
00269          */
00270         friend Vector operator-(const Point & p, const Point & q);
00271 
00272         /**
00273          * Find the point where this line meets the plane p.
00274          * Sets error BAD_LINE if the line lies within the plane.
00275          * \return the Point at which Line \c k meets Plane \c p.
00276          */
00277         friend Point meet(Line & k, Plane & p);
00278 
00279         /**
00280          * Compare two points.
00281          * This function returns \c true only if corresponding components are exactly equal.
00282          * Values that are theoretically equal but computed in different ways are likely
00283          * to be unequal according to this function.
00284          */
00285         friend bool operator==(const Point & p, const Point & q);
00286 
00287         /**
00288          * Compare two points.
00289          * This function returns \c false only if corresponding components are exactly equal.
00290          * Values that are theoretically equal but computed in different ways are likely
00291          * to be unequal according to this function.
00292          */
00293         friend bool operator!=(const Point & p, const Point & q);
00294 
00295         /**
00296          * Write "(x,y,z,w)" to output stream.
00297          * Inserts the coordinates of the point into the output stream \c os
00298          * in the format "(x,y,z,w)".  The current settings of the stream formatting
00299          * parameters are used.  If a width is specified with \c setw(), it is applied
00300          * to each coordinate, not to the point as a whole.
00301          */
00302         friend std::ostream & operator<<(std::ostream & os, Point & p);
00303 
00304         /**
00305          * Return the distance between a Point and a Plane.
00306          * The result has the correct magnitude only if the Point and the Plane
00307          * are both in normal form.  In particular, the result is incorrect if
00308          * the Point is at infinity.  However, the sign of the result is correct
00309          * in all cases, and so it is not necessary to provide normalized
00310          * arguments if only the sign is important.
00311          */
00312         friend GLfloat dist(const Point & p, const Plane & s);
00313 
00314         /**
00315          * Return the distance between a Point and a Plane.
00316          * The result has the correct magnitude only if the Point and the Plane
00317          * are both in normal form.  In particular, the result is incorrect if
00318          * the Point is at infinity.  However, the sign of the result is correct
00319          * in all cases, and so it is not necessary to provide normalized
00320          * arguments if only the sign is important.
00321          */
00322         friend GLfloat dist(const Plane & s, const Point & p);
00323 
00324         /**
00325          * Return the disgtance bewteen two points.
00326          * \note Does not check that the points are normalized.
00327          */
00328         friend double dist(const Point & p, const Point & q)
00329         {
00330             return sqrt((p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y) + (p.z - q.z) * (p.z - q.z));
00331         }
00332 
00333     private:
00334 
00335         /** X coordinate of point. */
00336         GLfloat x;
00337 
00338         /** Y coordinate of point. */
00339         GLfloat y;
00340 
00341         /** Z coordinate of point. */
00342         GLfloat z;
00343 
00344         /** W coordinate of point. */
00345         GLfloat w;
00346 
00347     };
00348 
00349 
00350     /**
00351      * An instance is a line defined by two Points.
00352      * Lines are occasionally useful.  For example, it is simple to
00353      * display surface normals using this class.
00354      * A Line is represented by the two Points which are its end-points.
00355      */
00356 
00357     class Line
00358     {
00359     public:
00360 
00361         friend class Plane;
00362 
00363         /**
00364          * Construct the Line from Point \c p to Point \c q.
00365          */
00366         Line(Point & p, Point & q);
00367 
00368         /**
00369          * Construct the Line from Point \c p to Point \c p+v.
00370          */
00371         Line(Point & p, Vector & v);
00372 
00373         /**
00374          * Find the point where this line meets the plane p.
00375          */
00376         friend Point meet(Line & k, Plane & p);
00377 
00378         /**
00379          * Draw the line using \c glBegin(GL_LINE) ....
00380          */
00381         void draw() const;
00382 
00383         /**
00384          * Compare two lines.
00385          * This function returns \c true only if corresponding components are exactly equal.
00386          * Values that are theoretically equal but computed in different ways are likely
00387          * to be unequal according to this function.
00388          */
00389         friend bool operator==(const Line & x, const Line & y);
00390 
00391         /**
00392          * Compare two lines.
00393          * This function returns \c false only if corresponding components are exactly equal.
00394          * Values that are theoretically equal but computed in different ways are likely
00395          * to be unequal according to this function.
00396          */
00397         friend bool operator!=(const Line & x, const Line & y);
00398 
00399         /**
00400          * Write a representation of the line to the output stream.
00401          * The format is \a pt->pt where "\a pt" is the format used for points.
00402          * If \c setw is used to set the width, it is passed to the inserter
00403          * for Point.
00404          */
00405         friend std::ostream & operator<<(std::ostream & os, Line & k);
00406 
00407     private:
00408         /** Start point of line. */
00409         Point s;
00410 
00411         /** Finish point of line. */
00412         Point f; // finish point
00413     };
00414 
00415 
00416     /**
00417      * An instance is a plane defined by its equation \a Ax+By+Cx+D=0.
00418      *
00419      * Planes are used for clipping, shadows, and reflections
00420      * (see class Matrix).
00421      *
00422      * Homogeneous points (x,y,z,w) lie on the plane if Ax+By+Cz+Dw=0.
00423      * The notation for a plane is \a <A,B,C,D>.  The plane \a <0,0,0,D> is undefined.
00424      * An attempt to construct such a plane sets the error flag to BAD_PLANE and the
00425      * plane is set to <0,1,0,0> (in the conventional OpenGL frame, this often corresponds
00426      * to the ground, \a y=0).
00427      *
00428      * A Plane is in normal form if the Vector \a (A,B,C) is a unit vector.
00429      * A Plane can be normalized by scaling \a A,B,C,D.
00430      */
00431 
00432     class Plane
00433     {
00434         friend class Matrix;
00435 
00436     public:
00437         /**
00438          * Construct a plane given the coefficients of its equation \a Ax+By+Cx+D=0.
00439          * If no arguments are provided, construct the plane y = 0.
00440          */
00441         Plane(GLfloat a = 0, GLfloat b = 1, GLfloat c = 0, GLfloat d = 0);
00442 
00443         /**
00444          * Construct a plane containing the three given points.
00445          */
00446         Plane(Point & p, Point & q, Point & r);
00447 
00448         /**
00449          * Construct a plane containing the line \c s and the point \c p.
00450          */
00451         Plane(Line & s, Point & p);
00452 
00453         /**
00454          * Construct the plane orthogonal to \c v and passing through \c p.
00455          */
00456         Plane(Vector & v, Point & p);
00457 
00458         /**
00459          * Normalize this plane.
00460          * The Plane \a (A,B,C,D) is in normal form when \a (A,B,C) is a unit vector.
00461          * Error ZERO_DIVISOR reported if \a |(A,B,C|=0 (which should not be the case for a well-formed plane).
00462          * \note The value of the Plane is changed by this function.
00463          */
00464         void normalize();
00465 
00466         /**
00467          * Return a normalized Plane equivalent to this plane.
00468          * The Plane \a (A,B,C,D) is in normal form when \a (A,B,C) is a unit vector.
00469          * Error ZERO_DIVISOR reported if \a |(A,B,C|=0 (which should not be the case for a well-formed plane).
00470          */
00471         Plane unit() const;
00472 
00473         /**
00474          * Return a vector of unit length that is normal to the plane.
00475          */
00476         Vector normal() const;
00477 
00478         /**
00479          * Use this plane as a clipping plane.
00480          * This function calls \c glClipPlane
00481          * to suppress rendering of objects on one side of the plane.
00482          * \param index must be one of GL_CLIP_PLANE0, GL_CLIP_PLANE1, ...  A
00483          * An implementation of OpenGL is supposed to provide at least six
00484          * clipping planes, numbered 0,1,...,5.
00485          */
00486         void clipPlane(GLenum index) const;
00487 
00488         /**
00489          * Find the point where this line meets the plane p.
00490          */
00491         friend Point meet(Line & k, Plane & p);
00492 
00493         /**
00494          * Compare two planes.
00495          * This function returns \c true only if corresponding components are exactly equal.
00496          * Values that are theoretically equal but computed in different ways are likely
00497          * to be unequal according to this function.
00498          */
00499         friend bool operator==(const Plane & x, const Plane & y);
00500 
00501         /**
00502          * Compare two planes.
00503          * This function returns \c false only if corresponding components are exactly equal.
00504          * Values that are theoretically equal but computed in different ways are likely
00505          * to be unequal according to this function.
00506          */
00507         friend bool operator!=(const Plane & x, const Plane & y);
00508 
00509         /**
00510          * Write a description of the plane to the output stream as \a <a,b,c,d>.
00511          * Inserts the components of the plane into the output
00512          * stream \c os in the format \a <a,b,c,d>.  The current settings
00513          * of the stream formatting parameters are used.  If a width
00514          * is specified with \c setw(), it is applied to each component
00515          * rather than to the plane as a whole.
00516          */
00517         friend std::ostream & operator<<(std::ostream & os, Plane & p);
00518 
00519         /**
00520          * Return the distance between a Point and a Plane.
00521          * The result has the correct magnitude only if the Point and the Plane
00522          * are both in normal form.  In particular, the result is incorrect if
00523          * the Point is at infinity.  However, the sign of the result is correct
00524          * in all cases, and so it is not necessary to provide normalized
00525          * arguments if only the sign is important.
00526          */
00527         friend GLfloat dist(const Point & p, const Plane & s);
00528 
00529         /**
00530          * Return the distance between a Point and a Plane.
00531          * The result has the correct magnitude only if the Point and the Plane
00532          * are both in normal form.  In particular, the result is incorrect if
00533          * the Point is at infinity.  However, the sign of the result is correct
00534          * in all cases, and so it is not necessary to provide normalized
00535          * arguments if only the sign is important.
00536          */
00537         friend GLfloat dist(const Plane & s, const Point & p);
00538 
00539 
00540     private:
00541         /** Coefficient of \a x in the plane equation. */
00542         GLfloat a;
00543 
00544         /** Coefficient of \a y in the plane equation. */
00545         GLfloat b;
00546 
00547         /** Coefficient of \a z in the plane equation. */
00548         GLfloat c;
00549 
00550         /** Coefficient of \a w in the plane equation. */
00551         GLfloat d;
00552     };
00553 
00554 
00555     /**
00556      * An instance is a vector with 3 real components.
00557      * A vector v is a 3-vector represented by three orthogonal components
00558      * \a vx, \a vy, and \a vz.  The norm of the vector \a v is vx*vx+vy*vy+vz*vz.
00559      * The length of \c v is \c sqrt(norm(v)).
00560      */
00561     class Vector
00562     {
00563         friend class Point;
00564         friend class Matrix;
00565         friend class Quaternion;
00566 
00567     public:
00568         /**
00569          * Construct the zero vector: (0,0,0).
00570          */
00571         Vector()
00572                 : x(0), y(0), z(0)
00573         {}
00574 
00575         /**
00576          * Construct the vector (x,y,z).
00577          */
00578         Vector(GLfloat x, GLfloat y, GLfloat z)
00579                 : x(x), y(y), z(z)
00580         {}
00581 
00582         /**
00583          * Construct a vector from the array \c coordinates.
00584          * \pre The array must have at least three components.
00585          */
00586         Vector(GLfloat coordinates[]);
00587 
00588         /**
00589          * Construct a vector normal to the polygon defined
00590          * by the given points using Martin Newell's algorithm.
00591          * The normal vector will be exact if the points lie in a plane,
00592          * otherwise it will be a sort of average value.  As with OpenGL,
00593          * the vector will point in the direction from which the points
00594          * are enumerated in a counter-clockwise direction.
00595          *
00596          * Unlike other functions, this function does \b not use homogeneous coordinates.
00597          * The points are assumed to have (x,y,z) coordinates; the w component is ignored.
00598          * \param points is an array of points.
00599          * \param numPoints is the number of points in the array.
00600          * \return the vector normal to the plane defined by \a points.
00601          * \note The vector is \b not a unit vector because it will probably
00602          * be averaged with other vectors.
00603          */
00604         Vector(Point points[], int numPoints);
00605 
00606         /**
00607          * Construct a vector from two points.
00608          * Vector(p, q) is equivalent to p - q.
00609          */
00610         Vector(Point & p, Point & q);
00611 
00612         /**
00613          * Construct a vector from a quaternion by ignoring the scalar component of the quaternion.
00614          * Vector(q) constructs the vector returned by \c q.vector().
00615          * \param q is the \a Quaternion whose vector component is to be used.
00616          */
00617         Vector(const Quaternion & q);
00618 
00619         /**
00620          * Add vector \c v to this vector.
00621          */
00622         Vector operator+=(const Vector & v);
00623 
00624         /**
00625          * Subtract vector \c v from this vector.
00626          */
00627         Vector operator-=(const Vector & v);
00628 
00629         /**
00630          * Return Vector (-x,-y,-z).
00631          */
00632         Vector operator-() const;
00633 
00634         /**
00635          * Multiply each component of the vector by \c scale.
00636          */
00637         Vector operator*=(GLfloat scale);
00638 
00639         /**
00640          * Return the vector (x/scale,y/scale,z/scale).
00641          * Error ZERO_DIVISOR reported if \c scale is zero.
00642          * \return the Vector (x/scale,y/scale,z/scale).
00643          */
00644         Vector operator/(GLfloat scale) const;
00645 
00646         /**
00647          * Divide each component of this vector by \c scale and return the new value.
00648          * Error ZERO_DIVISOR reported if \c scale is zero.
00649          */
00650         Vector operator/=(GLfloat scale);
00651 
00652         /**
00653          * Normalize this vector.
00654          * See also \a Vector::unit().
00655          * Reports error ZERO_NORM if the vector is zero.
00656          * \note  The value of this vector is changed by this operation.
00657          */
00658         void normalize();
00659 
00660         /**
00661          * Return a unit vector with the same direction as this vector.
00662          * See also \a Vector::normalize().
00663          * Reports error ZERO_NORM if the vector is zero.
00664          * \note The value of this vector is not changed by this operation.
00665          */
00666         Vector unit() const;
00667 
00668         /**
00669          * Return the norm of this vector.
00670          * The norm of a vector is the sum of its squared components
00671          * and is also the square of the length.
00672          * \return the norm of this vector.
00673          */
00674         GLfloat norm() const;
00675 
00676         /**
00677          * Return the length of this vector.
00678          * The length of a vector is the square root of its norm.
00679          * \return the length of this vector.
00680          */
00681         GLfloat length() const;
00682 
00683         /**
00684          * Use this vector to translate an object.
00685          * This is implemented by passing the vector to \c glTranslate().
00686          */
00687         void translate() const;
00688 
00689         /**
00690          * Use this vector as a normal vector when drawing a surface.
00691          * This is implemented by passing the vector to \c glNormal().
00692          */
00693         void drawNormal() const;
00694 
00695         /**
00696          * Draw this vector as a line in the graphics window.
00697          * The line joins \a P and \a P+V, where \a P is the point provided.
00698          * \param p is the start point for the vector.
00699          */
00700         void draw(const Point & p) const;
00701 
00702         /**
00703          * Get or set a reference to a component of this vector.
00704          * \c v[0] is the \a x component; \c v[1] is the \a y component; \c v[2] is the \a z component.
00705          * Error BAD_INDEX reported if \c i is not one of 0, 1, 2.
00706          */
00707         GLfloat & operator[](int i);
00708 
00709         /**
00710          * Get a reference to a component of this vector.
00711          * This form is used for \c const instances (\c v[i] cannot appear on the left of \c =).
00712          * \c v[0] is the \a x component; \c v[1] is the \a y component; \c v[2] is the \a z component.
00713          * Error BAD_INDEX reported if \c i is not one of 0, 1, 2.
00714          */
00715         const GLfloat & operator[](int i) const;
00716 
00717         /**
00718          * Return cross product of vectors \c u and \c v.
00719          */
00720         friend Vector cross(const Vector & u, const Vector & v);
00721 
00722         /**
00723          * Return cross product of vectors \c u and \c v.
00724          */
00725         friend Vector operator*(const Vector & u, const Vector & v);
00726 
00727         /**
00728          * Return dot product of vectors \c u and \c v.
00729          */
00730         friend GLfloat dot(const Vector & u, const Vector & v);
00731 
00732         /**
00733          * Return Vector \a s*v.
00734          */
00735         friend Vector operator*(const Vector & v, GLfloat s);
00736 
00737         /**
00738          * Return Vector \a s*v.
00739          */
00740         friend Vector operator*(GLfloat s, const Vector & v);
00741 
00742         /**
00743          * Return Vector \a u+v.
00744          */
00745         friend Vector operator+(const Vector & u, const Vector & v);
00746 
00747         /**
00748          * Return Vector \a u-v.
00749          */
00750         friend Vector operator-(const Vector & u, const Vector & v);
00751 
00752         /**
00753          * Displace a Point with a Vector.
00754          * \return Point at (p.x+p.w*v.x, p.y+p.w*v.y, p.z+p.w*v.z, p.w).
00755          */
00756         friend Point operator+(const Vector & v, const Point & p);
00757 
00758         /**
00759          * Return Point \c p displaced by vector \c v.
00760          */
00761         friend Point operator+(const Point & p, const Vector & v);
00762 
00763         /**
00764          * Compare two vectors.
00765          * This function returns \c true only if corresponding components are exactly equal.
00766          * Values that are theoretically equal but computed in different ways are likely
00767          * to be unequal according to this function.
00768          */
00769         friend bool operator==(const Vector & x, const Vector & y);
00770 
00771         /**
00772          * Compare two vectors.
00773          * This function returns \c false only if corresponding components are exactly equal.
00774          * Values that are theoretically equal but computed in different ways are likely
00775          * to be unequal according to this function.
00776          */
00777         friend bool operator!=(const Vector & x, const Vector & y);
00778 
00779         /**
00780          * Write vector to output stream as \a (x,y,z).
00781          * Inserts the components of the vector into the output
00782          * stream \c os in the format \a (x,y,z).  The current settings
00783          * of the stream formatting parameters are used.  If a width
00784          * is specified with \c setw(), it is applied to each coordinate,
00785          * not to the vector as a whole.
00786          */
00787         friend std::ostream & operator<<(std::ostream & os, Vector & v);
00788 
00789     private:
00790 
00791         /** X component of vector. */
00792         GLfloat x;
00793 
00794         /** Y component of vector. */
00795         GLfloat y;
00796 
00797         /** Z component of vector. */
00798         GLfloat z;
00799     };
00800 
00801     /**
00802      * Unit vector parallel to \a X axis.
00803      */
00804     const Vector I(1, 0, 0);
00805 
00806     /**
00807      * Unit vector parallel to \a Y axis.
00808      */
00809     const Vector J(0, 1, 0);
00810 
00811 
00812     /**
00813      * Unit vector parallel to \a Z axis.
00814      */
00815     const Vector K(0, 0, 1);
00816 
00817     /**
00818      * An instance is a matrix compatible with an OpenGL transformation matrix.
00819      * An instance of class Matrix is a 4 by 4 matrix with
00820      * components of type \c GLfloat.  The components are ordered
00821      * in the same way as an OpenGL matrix (column-row order,
00822      * for compatibility with FORTRAN).
00823 
00824      * Note that OpenGL performs matrix calculations very efficiently.
00825      * As far as possible, construct transformations using sequences of
00826      * OpenGL matrix operations.  Construct and use the matrices here
00827      * only if OpenGL does not provide the required facilities.
00828      */
00829     class Matrix
00830     {
00831     public:
00832 
00833         /**
00834          * Construct the identity matrix.
00835          */
00836         Matrix();
00837 
00838         /**
00839          * Construct a copy of an arbitrary OpenGL matrix.
00840          */
00841         Matrix(GL_Matrix r);
00842 
00843         /**
00844          * Construct a copy of an OpenGL projection or model view matrix.
00845          \param mode should be \c GL_PROJECTION_MATRIX or \c GL_MODELVIEW_MATRIX.
00846 
00847          Report error BAD_MATRIX_MODE and construct identity matrix
00848          for other values of mode.
00849          */
00850         Matrix(GLenum mode);
00851 
00852         /**
00853          * Construct a rotation matrix.
00854          \param axis is the axis of rotation.
00855          \param theta is the magnitude of the rotation.
00856          \note The angle \c theta should be in radians (unlike OpenGL, which uses degrees).
00857          */
00858         Matrix(const Vector & axis, double theta);
00859 
00860         /**
00861          * Construct a matrix that reflects a point in the given plane.
00862          * The matrix can be used to simulate a mirror in an OpenGL program.
00863          * See also Matrix::reflect().
00864          \param refl is the plane of reflection.
00865          */
00866         Matrix(const Plane & refl);
00867 
00868         /**
00869          * Construct a shadow matrix from a point light source and a plane.
00870          * The matrix transforms an object into its shadow on the given plane.
00871          * It is your job to ensure that the shadow has the appropriate colour, transparency, etc.
00872          * The light source may be a local point (w > 0) or a point at infinity (w = 0).
00873          * See also \c Matrix::shadow().
00874            \param lightPos is the position of the light source.
00875            \param plane is the plane onto which the shadow is projected.
00876 
00877          */
00878         Matrix(const Point & lightPos, const Plane & plane);
00879 
00880         /**
00881          * Construct a rotation matrix from a quaternion.
00882          * \pre The quaternion must be a unit quaternion.
00883          */
00884         Matrix(const Quaternion & q);
00885 
00886         /**
00887          * Construct the matrix that rotates one vector to another.
00888          * \param u is a vector representing an initial orientation.
00889          * \param v is a vector representing the final orientation.
00890          * The matrix, applied to \a u, will yield \a v.
00891          * \pre The vectors \a u and \a v must be unit vectors.
00892          */
00893         Matrix(const Vector & u, const Vector & v);
00894 
00895         /**
00896          * Return the quaternion corresponding to this matrix.
00897          * This function may report BAD_ROTATION_MATRIX.
00898          * \note The result may be imprecise if the rotation angle is close to 180 degrees.
00899          * \pre The matrix must be a rotation matrix.
00900          */
00901         Quaternion quaternion() const;
00902 
00903         /**
00904          * Return a pointer to the first element of the matrix.
00905          * This function may be used in conjunction with
00906          * \c glMultMatrix() to apply this matrix to the current OpenGL matrix.
00907          * \return a pointer to the first element of the matrix.
00908          */
00909         GLfloat *get()
00910         ;
00911 
00912         /**
00913          * Return the transpose of this matrix.
00914          */
00915         Matrix transpose() const;
00916 
00917         /**
00918          * Return the inverse of this matrix.
00919          * The function uses Cramer's method: compute the matrix of cofactors
00920          * and divide each element by the determinant.
00921          * If the matrix is singular, report \c SINGULAR_MATRIX and return the zero matrix.
00922          * The prefix operator ~ has the same effect.
00923          * \return the inverse of this matrix.
00924          */
00925         Matrix inv() const;
00926 
00927         /**
00928          * Return the inverse of this matrix.
00929          * This provides an alternative syntax for inv().
00930          * \return the inverse of this matrix.
00931          */
00932         Matrix operator~() const;
00933 
00934         /**
00935          * Multiply the current OpenGL matrix by this matrix.
00936          */
00937         void apply() const;
00938 
00939         /**
00940          * Apply this matrix to a point.
00941          */
00942         Point apply(const Point & p) const;
00943 
00944         /**
00945          * Apply this matrix to a vector.
00946          */
00947         Vector apply(const Vector & v) const;
00948 
00949         /**
00950          * Return the axis of a rotation matrix.
00951          * Report error \c BAD_ROTATION_MATRIX and leave result undefined,
00952          * if the matrix is not a rotation.
00953          * \return the axis of a rotation matrix.
00954          */
00955         Vector axis() const;
00956 
00957         /**
00958          * Return the angle (in radians) of a rotation matrix.
00959          * Report error \c BAD_ROTATION_MATRIX and leave result undefined,
00960          * if the matrix is not a rotation.
00961          * \return the angle (in radians) of a rotation matrix.
00962          */
00963         double angle() const;
00964 
00965         /**
00966          * Return a reference to the element \c m[i][j] of the matrix.
00967          * \pre The values of \c i and \c j must be in the range [0,3].
00968          * \return the element \c m[i][j] of the matrix.
00969          */
00970         GLfloat & operator()(int i, int j);
00971 
00972         /**
00973          * Return a reference to the element \c m[i][j] of the \c const matrix.
00974          * This version is used for \c const instances (\c m(i,j) cannot appear on the left of \c =).
00975          * \pre The values of \c i and \c j must be in the range [0,3].
00976          * \return the element \c m[i][j] of the matrix.
00977          */
00978         const GLfloat & operator()(int i, int j) const;
00979 
00980         /**
00981          * Set the matrix so that it reflects a point in the plane \c p.
00982          * The matrix can be used to simulate a mirror in an OpenGL program.
00983          * See also constructors for class Matrix.
00984            \param p is the plane of reflection.
00985          */
00986         void reflect(const Plane & p);
00987 
00988         /**
00989          * Set the matrix so that it creates a shadow on the plane \c p from a light source \c lightPos.
00990          * The matrix transforms an object into its shadow on the given plane.
00991          * It is your job to ensure that the shadow has the appropriate colour, transparency, etc.
00992          * The point \c p may be either a local point (w > 0) or a point at infinity (w = 0).
00993          * See also constructors for class Matrix.
00994          \param lightPos is the position of the light source causing the shadow.
00995          \param plane is the plane upon which the shadow is cast.
00996          */
00997         void shadow(const Point & lightPos, const Plane & plane);
00998 
00999         /**
01000          * Multiply two matrices.
01001          */
01002         friend Matrix operator*(const Matrix & m, const Matrix & n);
01003 
01004         /**
01005          * Compare two matrices.
01006          * This function returns \c true only if corresponding components are exactly equal.
01007          * Values that are theoretically equal but computed in different ways are likely
01008          * to be unequal according to this function.
01009          */
01010         friend bool operator==(const Matrix & x, const Matrix & y);
01011 
01012         /**
01013          * Compare two matrices.
01014          * This function returns \c false only if corresponding components are exactly equal.
01015          * Values that are theoretically equal but computed in different ways are likely
01016          * to be unequal according to this function.
01017          */
01018         friend bool operator!=(const Matrix & x, const Matrix & y);
01019 
01020         /**
01021          * Write a four-line image of the matrix to the output stream.
01022          * The current settings of the stream formatting parameters are used.
01023          * If a width is specified with \c setw(), it is applied to each
01024          * element of the matrix, not the matrix as a whole.
01025          */
01026         friend std::ostream & operator<<(std::ostream & os, Matrix & m);
01027 
01028     private:
01029 
01030         /** The elements of the matrix. */
01031         GL_Matrix m;
01032     };
01033 
01034 
01035 
01036     /**
01037      * An instance is a quaternion represented as a (scalar, vector) pair.
01038      * We use the notation \a (s,v) for a quaternion with scalar component
01039      *   \a s and vector component \a v.  Although arbitrary quaternions can be
01040      *   constructed, all of the applications of quaternions provided by
01041      *   the class assume that the quaternion is a unit quaternion
01042      *   representing a rotation.
01043      */
01044     class Quaternion
01045     {
01046     public:
01047 
01048         friend class Vector;
01049         friend class Matrix;
01050 
01051         /**
01052          * Construct the quaternion (1,(0,0,0)) (the null rotation).
01053          */
01054         Quaternion() : s(1)
01055         {}
01056 
01057         /**
01058          * Construct the quaternion (s, (x,y,z)).
01059          */
01060         Quaternion(GLfloat s, GLfloat x, GLfloat y, GLfloat z)
01061                 : s(s), v(Vector(x,y,z))
01062         {}
01063 
01064         /**
01065          * Construct the quaternion \a (0,v).
01066          * The result will be a unit quaternion if \a v is a unit vector,
01067          * in which case the quaternion represents a rotation through
01068          * 90 degrees about the axis \a v.
01069          */
01070         Quaternion(const Vector & v) : s(0), v(v)
01071         {}
01072 
01073         /**
01074          * Construct the quaternion \a (s,v).
01075          * \note Don't confuse this constructor with Quaternion(axis,angle).
01076          * \param s is the scalar component of the quaternion.
01077          * \param v is the vector component of the quaternion.
01078          */
01079         Quaternion(GLfloat s, const Vector & v) : s(s), v(v)
01080         {}
01081 
01082         /**
01083          * Construct a quaternion with the given axis of rotation and angle.
01084          * \note Don't confuse this constructor with Quaternion(s,v).
01085          * \pre The axis must be a unit vector.
01086          * \param axis gives the axis of rotation.
01087          * \param angle gives the amount of the rotation.
01088          */
01089         Quaternion(Vector axis, double angle)
01090                 : s(GLfloat(cos(angle/2))), v(GLfloat(sin(angle/2)) * axis)
01091         {}
01092 
01093         /**
01094          * Construct the quaternion corresponding to an OpenGL rotation matrix.
01095          * The result may be imprecise if the rotation angle is close to 180 degrees.
01096          * This function may report BAD_ROTATION_MATRIX.
01097          * \pre The matrix must be a rotation matrix.
01098          */
01099         Quaternion(Matrix m);
01100 
01101         /**
01102          * Construct a quaternion from Euler angles.
01103          */
01104         Quaternion(double xr, double yr, double zr);
01105 
01106         /**
01107          * Construct a Quaternion from a Point.
01108          * The quaternion consists of the vector \a (p[0],p[1],p[2]) and the scalar \a p[3].
01109          * \note This is a unusual operation and should not normally be used.
01110          * It is intended for experiments with non-linear transformations.
01111          */
01112         Quaternion(const Point & p);
01113 
01114         /**
01115          * Construct the quaternion that rotates one vector to another.
01116          * \param u is a vector representing an initial orientation.
01117          * \param v is a vector representing the final orientation.
01118          * The quaternion, applied to \a u, will yield \a v.
01119          * \pre The vectors \a u and \a v must be unit vectors.
01120          */
01121         Quaternion(const Vector & u, const Vector & v);
01122 
01123         /**
01124          * Return the quaternion \a q+r.
01125          * \note The sum of two unit quaternions is not in general a unit quaternion.
01126          * However, it occasionally appears in expressions such as k q1 + (1 - k) q2,
01127          * which does yield a unit quaternion.
01128          * \return the Quaternion \a q+r.
01129          */
01130         friend Quaternion operator+(const Quaternion & q, const Quaternion & r);
01131 
01132         /**
01133          * Return the quaternion \a q-r.
01134          * \note The difference of two unit quaternions is not in general a unit quaternion.
01135          * \return the Quaternion \a q-r.
01136          */
01137         friend Quaternion operator-(const Quaternion & q, const Quaternion & r);
01138 
01139         /**
01140          * Return the quaternion product \a q*r.
01141          * If \c q and \c r represent
01142          * rotations, then \a q*r represents the rotation \a q followed by the rotation \a r.
01143          * \note Quaternion multiplication is not commutative: \a q*r is not equal to \a r*q.
01144          * \return the Quaternion product \a q*r.
01145          */
01146         friend Quaternion operator*(const Quaternion & q, const Quaternion & r);
01147 
01148         /**
01149          * Promote the vector \a v to a quaternion \a qv and
01150          * return the quaternion product \a qv*q.
01151          */
01152         friend Quaternion operator*(const Vector & v, const Quaternion & q);
01153 
01154         /**
01155          * Promote the vector \a v to a quaternion \a qv and
01156          * return the quaternion product \a q*qv.
01157          */
01158         friend Quaternion operator*(const Quaternion & q, const Vector & v);
01159 
01160         /**
01161          * Return the quaternion ratio \a q/r.
01162          * If q and r represent
01163          * rotations, then \a q/r represents the rotation \a q followed by
01164          * the rotation that is the inverse of \a r.
01165          * \return the Quaternion ratio \a q/r.
01166          */
01167         friend Quaternion operator/(const Quaternion & q, const Quaternion & r);
01168 
01169         /**
01170          * Multiply this quaternion by \c q and return the result.
01171          */
01172         Quaternion operator*=(const Quaternion & q);
01173 
01174         /**
01175          * Divide this quaternion by \c q and return the result.
01176          */
01177         Quaternion operator/=(const Quaternion & q);
01178 
01179         /**
01180          * Return the quaternion \a a*q, where \a a is a scalar.
01181          * \a a is a scalar and a*(s,v) = (a*s, a*v).
01182          * \return the Quaternion \a a*q.
01183          */
01184         friend Quaternion operator*(const Quaternion & q, GLfloat a);
01185 
01186         /**
01187          * Return the quaternion \a a*q, where \a a is a scalar.
01188          * \a a is a scalar and a*(s,v) = (a*s, a*v).
01189          * \return the Quaternion \a a*q.
01190          */
01191         friend Quaternion operator*(GLfloat a, const Quaternion & q);
01192 
01193         /**
01194          * Return the quaternion \a q/a, where \a a is a scalar.
01195          * \a a is a scalar and (s,v)/a = (s/a, v/a).
01196          * Report error ZERO_DIVISOR if \a a = 0.
01197          * \return the Quaternion \a q/a.
01198          */
01199         Quaternion operator/(GLfloat scale) const;
01200 
01201         /**
01202          * Normalize this quaternion.
01203          * See also Quaternion::unit().
01204          * Report error ZERO_DIVISOR if q = (0,(0,0,0)).
01205          * \note The value of this quaternion is changed by this operation.
01206          */
01207         void normalize();
01208 
01209         /**
01210          * Return a unit quaternion corresponding to this quaternion.
01211          * See also Quaternion::normalize().
01212          * Report error ZERO_DIVISOR if q = (0,(0,0,0)).
01213          * \note The value of this quaternion is not changed by this operation.
01214          */
01215         Quaternion unit() const;
01216 
01217         /**
01218          * Return the conjugate of this quaternion.
01219          * The conjugate of (s,v) is (s,-v).
01220          * The inverse and conjugate of a unit quaternion are equal.
01221          * \return the conjugate of this quaternion.
01222          */
01223         Quaternion conj() const;
01224 
01225         /**
01226          * Return Inverse of this quaternion.
01227          * q.inv() = q.conj()/q.norm().
01228          * The inverse and conjugate of a unit quaternion are equal.
01229          * Report error ZERO_DIVISOR if q.norm() = 0.
01230          * If \c q represents a rotation then \c q.inv() represents
01231          * the opposite, or inverse, rotation.
01232          * The prefix operator ~ has the same effect.
01233          * \return the inverse of this quaternion.
01234          */
01235         Quaternion inv() const;
01236 
01237         /**
01238          * Return Inverse of this quaternion.
01239          * This provides alternative syntax for \c inv().
01240          * \return the inverse of this quaternion.
01241          */
01242         Quaternion operator~() const;
01243 
01244         /**
01245          * Apply this quaternion to the vector \c w.
01246          * The vector \c w is not changed.
01247          * \return the rotated vector \c q.inv()*w*q.
01248          */
01249         Vector apply(const Vector & w) const;
01250 
01251         /**
01252          * Return Vector component \a v of the quaternion \a q = \a (s,v).
01253          * The same effect can be achieved with the constructor \c Vector::Vector(q).
01254          */
01255         Vector vector() const;
01256 
01257         /**
01258          * Return Scalar component \a s of the quaternion \a q = \a (s,v).
01259          */
01260         GLfloat scalar() const;
01261 
01262         /**
01263          * Return the norm of this quaternion.
01264          * The norm is the sum of the squared components
01265          * and is also the square of the magnitude.
01266          * \return the norm of this quaternion.
01267          */
01268         GLfloat norm() const;
01269 
01270         /**
01271          * Return the magnitude of this quaternion.
01272          * The magnitude is the square root of the norm.
01273          * \return the magnitude of this quaternion.
01274          */
01275         GLfloat magnitude() const;
01276 
01277         /**
01278          * Compute the rotation matrix corresponding to this quaternion
01279          * and store it in the Matrix \c m.
01280          */
01281         void matrix(Matrix & m) const;
01282 
01283         /**
01284          * Compute the rotation matrix corresponding to this quaternion
01285          * and store it in the OpenGL matrix \c m.
01286          */
01287         void matrix(GL_Matrix m) const;
01288 
01289         /**
01290          * Apply the current quaternion to the current OpenGL matrix.
01291          */
01292         void apply() const;
01293 
01294         /**
01295          * Return the axis of rotation of this quaternion.
01296          * \pre The quaternon must be a unit quaternion.
01297          * \return a unit vector giving the axis of rotation of the quaternion.
01298          */
01299         Vector axis() const;
01300 
01301         /**
01302          * Return the amount of rotation of this quaternion.
01303          * \pre The quaternon must be a unit quaternion.
01304          * \return the amount of rotation provided by this quaternion in radians.
01305          */
01306         double angle() const;
01307 
01308         /**
01309          * Integrate an angular velocity vector.
01310          * The rotation represented by this quaternion will be updated by
01311          * applying the angular velocity \c omega for a short interval of
01312          * time \c dt.
01313          * \param omega is an angular velocity vector.
01314          * \param dt is the time increment for integration.
01315          */
01316         void integrate(Vector & omega, double dt);
01317 
01318         /**
01319          * Return Euler angles for this quaternion.
01320          * The quaternion gives the rotation that would be obtained by calling
01321          * \c glRotatef three times, with arguments (\c xr,1,0,0), (\c yr,0,1,0), and
01322          * (\c zr,0,0,1).
01323          * \pre The angle transformations are applied in \a x, \a y, \a z order.
01324          * \return the Euler angles corresponding to this quaternion.
01325          */
01326         void euler(double & xr, double & yr, double & zr) const;
01327 
01328         /**
01329          * Use this quaternion to simulate a trackball.
01330          * To use this function in an OpenGL program, use the default constructor
01331          * to construct the quaternion \a q = (1,(0,0,0)).  In the display function,
01332          * use \c q.rotate() to modify the OpenGL model view matrix.
01333          *
01334          * Call \c trackball(x1,y1,x2,y2) to record a small mouse movement
01335          * from \a (x1,y1) to \a (x2,y2).  The coordinates should be normalized
01336          * so that both \a x and \a y are in [-1,1].
01337          *
01338          * This function will compute a rotation will apply this rotation to
01339          * the current quaternion.  The rotation simulates a trackball.
01340          */
01341         void trackball(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
01342 
01343         /**
01344          * The 'logarithm' of a unit quaternion is a vector.
01345          * This function is defined because it appears in descriptions of quaternions.
01346          * Although the name 'ln' is appropriate in some ways, this function must be used with
01347          * caution because it may not have the properties you expect of a logarithm.
01348          * For example, \a ln(q1)+ln(q2) makes sense only if \a q1 and \a q2 have the
01349          * same axis.
01350          * \pre The quaternion must be a unit quaternion.
01351          */
01352         friend Vector ln(const Quaternion & q);
01353 
01354         /**
01355          * The 'exponent' of a vector is a unit quaternion.
01356          * Although the name 'exp' is appropriate in some ways, this function must be used with
01357          * caution because it may not have the properties you expect of an exponent.
01358          * For example, \a exp(v1+v2)=exp(v1)*exp(v2) only if \a v1 and \a v2 have the same
01359          * direction.
01360          */
01361         friend Quaternion exp(const Vector & v);
01362 
01363         /**
01364          * Return the dot product of quaternions \c q and \c r.
01365          * The dot product of \a (s,u) and \a (t,v) is \a st+dot(u,v)
01366          * where \a dot(u,v) denotes the vector dot product of \a u and \a v.
01367          * \return the dot product of quaternions \c q and \c r.
01368          */
01369         friend GLfloat dot(const Quaternion & q, const Quaternion & r);
01370 
01371         /**
01372          * Compare two quaternions.
01373          * This function returns \c true only if corresponding components are exactly equal.
01374          * Values that are theoretically equal but computed in different ways are likely
01375          * to be unequal according to this function.
01376          */
01377         friend bool operator==(const Quaternion & x, const Quaternion & y);
01378 
01379         /**
01380          * Compare two quaternions.
01381          * This function returns \c false only if corresponding components are exactly equal.
01382          * Values that are theoretically equal but computed in different ways are likely
01383          * to be unequal according to this function.
01384          */
01385         friend bool operator!=(const Quaternion & x, const Quaternion & y);
01386 
01387         /**
01388          * Write the quaternion to the output stream as \a s \a (x,y,z).
01389          */
01390         friend std::ostream & operator<<(std::ostream & os, Quaternion & q);
01391 
01392     private:
01393 
01394         /** Scalar component of quaternion. */
01395         GLfloat s;
01396 
01397         /** Vector component of quaternion. */
01398         Vector v;
01399     };
01400 
01401 
01402 
01403     /**
01404      * An instance represents a camera.
01405      * An instance of class \c Camera is used to control the view.
01406      * The function \c Camera::apply() calls \c gluLookAt() with
01407      * appropriate parameters.  The other functions of this class
01408      * set up these parameters.
01409      *
01410      * Camera movements may be smooth (interlpolated between end
01411      * points) or abrupt.  The function Camera::setMode() determines
01412      * the kind of movement.
01413      * Smooth transitions are obtained by calling \c Camera::idle()
01414      * in the GLUT idle callback function, together with the various
01415      * camera movement functions.
01416      */
01417 
01418 
01419 
01420     //typedef void (BaseCamera::*IdleMemFunc)();
01421 
01422     //IdleMemFunc gIdleMemFunc;
01423 
01424     /**
01425     * All derived class must implement at least two
01426     * virtual functions \c BaseCamera::idle() which will
01427     * typically be called in the callback function for glutIdleFunc,
01428     * i.e. within callback function "idle()" DerivedClass::idle() will
01429     * be called and later in "main" callback "idle()" will be called
01430     * as parameter to "glutIdleFunc".
01431     * void idle() { DerivedClass::idle();}
01432     * int main() { ... glutIdleFunc(idle); ...}
01433     * \c BaseCamera::apply() const. Similarly inside callback function
01434     * for "glutDisplayFunc", say "display()", DerivedClass::apply() will be
01435     * called.
01436     * i.e. void display() { DerivedClass::apply();..}
01437     * int main(){...glutDisplayFunc(display); ...}
01438     *
01439     */
01440 
01441     class BaseCamera
01442     {
01443     public:
01444         /** Construct an instance of a \a BaseCamera.
01445          * This constructor is usually called from a subclass.
01446          */
01447         BaseCamera() : maxSteps(50), steps(0)
01448         {}
01449 
01450         /**
01451         * Set the number of steps required for a camera movement.
01452         * \param s is the number of steps executed during a movement.
01453         * \a s = 10 will give a rapid, possibly jerky, movement.
01454         * \a s = 100 will give a slow, smooth movement.
01455         */
01456         void setSteps(int s)
01457         {
01458             maxSteps=s;
01459         }
01460 
01461         /**
01462         * This function should be called from the GLUT idle() function
01463         * or its equivalent.  It performs one step of the motion until
01464         * the motion is complete, after which it has no effect.
01465         */
01466         virtual void idle()=0;
01467 
01468         /**
01469          * This function should be called from the GLUT display() function
01470          * or its equivalent.
01471          */
01472         virtual void apply() const =0;
01473 
01474         /**
01475         * This function is just a suggested wrapper for all derived class
01476         * for initializations, such as set up first and last position for
01477         * motions in /c Interpolator, or set up new eye and view parameter
01478         * for /c Camera. I don't want to force new class to wrap their
01479         * initialization actions within this function, so, I don't make this
01480         * method as abstract one.
01481         * (added by nick)
01482         */
01483         virtual void update()
01484         {}
01485 
01486     protected:
01487 
01488         /** Current value of step counter. */
01489         int steps;
01490 
01491         /** Maximum number of steps for a smooth movement. */
01492         int maxSteps;
01493 
01494     };
01495 
01496 
01497     /**
01498      * An instance represents a camera.
01499      * An instance of class \c Camera is used to control the view.
01500      * The function \c Camera::apply() calls \c gluLookAt() with
01501      * appropriate parameters.  The other functions of this class
01502      * set up these parameters.
01503      *
01504      * Camera movements may be smooth (interlpolated between end
01505      * points) or abrupt.  The function Camera::setMode() determines
01506      * the kind of movement.
01507      * Smooth transitions are obtained by calling \c Camera::idle()
01508      * in the GLUT idle callback function, together with the various
01509      * camera movement functions.
01510      */
01511     class Camera : public BaseCamera
01512     {
01513         //friend void myIdle();
01514     public:
01515 
01516         /**
01517          * Construct a default camera.  The view is set as follows:
01518          * Eye = (0,0,1).  Model=(0,0,0).  Up=(0,1,0).
01519          */
01520         Camera();
01521 
01522         /**
01523          * Construct a camera for a particular view.
01524          * \param eye sets the eye coordinates for \c gluLookAt().
01525          * \param model sets the model coordinates for \c gluLookAt().
01526          * \param up sets the 'up' vector for \c gluLookAt().
01527          */
01528         Camera(const Point & eye, const Point & model, const Vector & up);
01529 
01530         /**
01531          * Construct a camera for a particular view.
01532          * The 'up' vector is set to (0,1,0).
01533          * \param eye sets the eye coordinates for \c gluLookAt().
01534          * \param model sets the model coordinates for \c gluLookAt().
01535          */
01536         Camera(const Point & eye, const Point & model);
01537 
01538         /**
01539          * Construct a camera for a particular view.
01540          * The 'up' vector is set to (0,1,0).
01541          * The model point is set to (0,0,0).
01542          * \param eye sets the eye coordinates for \c gluLookAt().
01543          */
01544         Camera(const Point & eye);
01545 
01546         /**
01547          * Set the camera for a particular view.
01548          * \param eye sets the eye coordinates for \c gluLookAt().
01549          * \param model sets the model coordinates for \c gluLookAt().
01550          * \param up sets the 'up' vector for \c gluLookAt().
01551          */
01552         void set(const Point & eye, const Point & model, const Vector & up)
01553         ;
01554 
01555         /**
01556          * Set the camera for a particular view.
01557          * The 'up' vector is set to (0,1,0).
01558          * \param eye sets the eye coordinates for \c gluLookAt().
01559          * \param model sets the model coordinates for \c gluLookAt().
01560          */
01561         void set(const Point & eye, const Point & model)
01562         ;
01563 
01564         /**
01565          * Set the camera for a particular view.
01566          * The model point is set to (0,0,0).
01567          * The 'up' vector is set to (0,1,0).
01568          * \param eye sets the eye coordinates for \c gluLookAt().
01569          */
01570         void set(const Point & eye)
01571         ;
01572 
01573 
01574         /**
01575          * Update the camera position.
01576          * This function should be called from the GLUT idle() function
01577          * or its equivalent.  It performs one step of the motion until
01578          * the motion is complete, after which it has no effect.
01579          */
01580         virtual void idle();
01581 
01582         /**
01583          * Apply the camera position to the model-view matrix.
01584          * This function calls \c gluLookAt() with appropriate parameters.
01585          * It should be called in the GLUT display function or its equivalent
01586          * after the model-view matrix has been initialized.
01587          */
01588         void apply() const;
01589 
01590         /**
01591          * Move the camera upwards (+Y direction).
01592          * \param distance gives the amount of movement.  Negative values move
01593          * the camera downwards.
01594          */
01595         void moveUp(GLfloat distance);
01596 
01597         /**
01598          * Move the camera forwards.
01599          * The camera moves towards the model.
01600          * \param distance gives the amount of movement.  Negative values move
01601          * the camera away from the model..
01602          */
01603         void moveForward(GLfloat distance);
01604 
01605         /**
01606          * Move the camera to its left.
01607          * \param distance gives the amount of movement.  Negative values move
01608          * the camera to its right.
01609          */
01610         void moveLeft(GLfloat distance);
01611 
01612         /**
01613          * Tilt the camera upwards.
01614          * \param angle gives the angle through which the camera should be moved.
01615          * Negative values give a downward tilt.
01616          */
01617         void tiltUp(double angle);
01618 
01619         /**
01620          * Pan the camera to the left.
01621          * \param angle gives the angle through which the camera should be panned.
01622          * Negative values give panning to the right.
01623          */
01624         void panLeft(double angle);
01625 
01626         /**
01627          * Write a representation of the camera to a stream.
01628          * This function displays the current settings of the eye point,
01629          * the model point, and the up vector.
01630          * \param os is a reference to an output stream.
01631          * \param c is a reference to a camera.
01632          */
01633 
01634         /**
01635         * Set the kind of motion required.
01636         * \param mode should be set to \c true for smooth movements
01637         * or to \c false for abrupt movements.
01638         */
01639         void setMode(bool mode)
01640         {
01641             smooth=mode;
01642         }
01643 
01644         /** Write a textul representation of the camera's status.
01645          * \param os is the stream to which the desccription will be written.
01646          * \param c is a camera.
01647          */
01648         friend std::ostream & operator<<(std::ostream & os, Camera & c);
01649 
01650     protected:
01651 
01652         /** Update the camera position. */
01653         void update(Point & e, Point & m);
01654 
01655         /** Eye coordinates for gluLookAt(). */
01656         Point eye;
01657 
01658         /** Previous eye coordinates. */
01659         Point eyeOld;
01660 
01661         /** Updated eye coordinates. */
01662         Point eyeNew;
01663 
01664 
01665         /** Model coordinates for gluLookAt() */
01666         Point model;
01667 
01668         /** Previous model coordinates */
01669         Point modelOld;
01670 
01671         /** Updated model coordinates */
01672         Point modelNew;
01673 
01674         /** Up vector for gluLookAt() */
01675         Vector up;
01676 
01677         /** Mode for motion */
01678         bool smooth;
01679     };
01680 
01681     /**
01682      * An instance is an interpolator for rotations.
01683      * An instance of Interpolator is used to interpolate between two rotations.
01684      * In other words, given two orientations of an object, an interpolator can
01685      * be used to move the object smoothly from one orientation to the other.
01686      * An interpolator is represented by two quaternions representing the
01687      * extreme values of the rotations.  When a real number \a t in the interval
01688      * [0,1] is passed to the interpolator, the interpolator constructs a third
01689      * quaternion representing an intermediate orientation.  This quaternion can
01690      * be used to generate a rotation matrix or transform the OpenGL model view.
01691      *
01692      * The simplest way to use this class is as follows:
01693      *       -# Construct two quaternions, \a q and \a r, corresponding to the
01694      *          first and last positions of the desired movement.
01695      *       -# Construct an interpolator \a i(q,r).
01696      *       -# In the OpenGL display function, call \c i.apply(t), giving
01697      *          \a t a sequence of values ranging from 0 to 1.
01698      *
01699      *
01700      */
01701     class Interpolator: public BaseCamera
01702     {
01703     public:
01704 
01705         /**
01706          * Construct an interpolator with dummy values for the quaternions.
01707          * The interpolator may fail if it is used without first setting the
01708          * start and finish quaternions.  Use \c Quaternion::set() to change
01709          * the first and last quaternions to useful values.
01710          */
01711         Interpolator();
01712 
01713         /**
01714          * Construct an interpolator to rotate from \c qFirst to \c qLast.
01715          * Report error \c BAD_INTERPOLATOR_ARG if \c qFirst = \c qLast.
01716          */
01717         Interpolator(Quaternion & qFirst, Quaternion & qLast);
01718 
01719         /**
01720          * Change the first and last quaternions of an existing interpolator.
01721          * Report error \c BAD_INTERPOLATOR_ARG if \c qFirst = \c qLast.
01722          */
01723         void set(const Quaternion & qFirst, const Quaternion & qLast)
01724         ;
01725 
01726         /**
01727          * Perform the rotation at position \a t, 0 <= \a t <= 1
01728          * by modifying the current OpenGL transformation matrix.
01729          */
01730         void apply(double t) const;
01731 
01732         /**
01733          * Compute the rotation matrix for position \a t, 0 <= \a t <= 1.
01734          */
01735         void getMatrix(double t, GL_Matrix m) const;
01736 
01737         /**
01738          * Return the quaternion for position \a t, 0 <= \a t <= 1.
01739          */
01740         Quaternion getQuaternion(double t) const;
01741 
01742         /**
01743         * Update the Interpolator position.
01744         * This function should be called from the GLUT idle() function
01745         * or its equivalent.  It performs one step of the motion until
01746         * the motion is complete, after which it has no effect.
01747         */
01748         virtual void idle();
01749 
01750         /**
01751            * Apply the Interpolator rotation to the model-view matrix.
01752            * This function calls apply(t) with parameters t which is actually steps/maxSteps.
01753            * It should be called in the GLUT display function or its equivalent
01754            * after the model-view matrix has been initialized.
01755            */
01756         virtual void apply() const;
01757 
01758         /**
01759         * Update Interpolator first and last Quaternion.
01760            */
01761         virtual void update()
01762         {
01763             ;
01764         }
01765 
01766     protected:
01767 
01768         /** Initialize the interpolator. */
01769         void initialize();
01770 
01771         /** The quaternion currently in use. */
01772         Quaternion current;
01773 
01774         /** The start quaternion for the interpolation. */
01775         Quaternion first;
01776 
01777         /** The final quaternion for the interpolation. */
01778         Quaternion last;
01779 
01780         /** The angle between the first and last positions. */
01781         double omega;
01782 
01783         /** The sine of the angle between the first and last positions. */
01784         double sinOmega;
01785 
01786         /** The cosine of the angle between the first and last positions. */
01787         double cosOmega;
01788     };
01789 
01790 
01791 
01792     /**
01793       * An instance is an RGB pixel array.
01794       * An instance of PixelMap holds an array that OpenGL can use
01795       * as a texture or to display directly.
01796       *
01797       * This class is implemented so that it does not depend on Windows.
01798       * In principle, it should even work with Linux and other operating
01799       * systems, although this has not been tested thoroughly.
01800       *
01801       * If you want to use a \a BMP image as a texture, the width and height
01802       * must be powers of two.  Thus a 256 x 512 \a BMP image is acceptable
01803       * but a 640 x 400 image is not.  This restriction does not apply to
01804       * images that are displayed as bitmaps.
01805       *
01806       * Since an instance of \c PixelMap contains pointers, there are memory
01807       * management issues.  The destructor deletes pixel and other data
01808       * associated with a pixel map.  The copy constructor is declared privately
01809       * and not implemented: this prevents instances being passed by value,
01810       * although they may be passed by reference.  Since there is a default
01811       * constructor, you can construct arrays of PixelMap's or pointers to
01812       * PixelMap.
01813       */
01814     class PixelMap
01815     {
01816     public:
01817 
01818         /**
01819          * Construct an empty pixel map.
01820          */
01821         PixelMap();
01822 
01823         /**
01824          * Read a pixel map from a file.
01825          * \param bmpFileName is a path to a BMP file.
01826          */
01827         PixelMap(char *bmpFileName);
01828 
01829         /**
01830          * Construct a pixel map from a region of the pixel buffer.
01831          * \param x is the \a X coordinate of the lower left corner of the region.
01832          * \param y is the \a Y coordinate of the lower left corner of the region.
01833          * \param w is the width of the region in pixels.
01834          * \param h is the height of the region in pixels.
01835          * \note See also PixelMap::read(x, y, w, h).
01836          */
01837         PixelMap(GLint x, GLint y, GLsizei w, GLsizei h);
01838 
01839         /**
01840          * Delete a pixel map.
01841          */
01842         ~PixelMap();
01843 
01844         /**
01845          * Read a BMP file and convert it to a pixel map.
01846          * Previous data associated with this object will be deleted.
01847          * The BMP file must satisfy several criteria if it is to
01848          * be converted successfully.  Conversion failure is
01849          * indicated by the following CUGL errors.
01850          * \li \c OPEN_FAILED: the file could not be opened
01851          * \li \c NOT_BMP_FILE: the file is not a BMP file
01852          * \li \c NOT_24_BITS: the format is not 24 bits/pixel
01853          * \li \c COMPRESSED_BMP_FILE: the file is compressed
01854          * \li \c NOT_ENOUGH_MEMORY: there is not enough memory to store the data
01855          *
01856          * OpenGL cannot use a bitmap as a texture if its dimensions are not powers of 2.
01857          * To check whether the bitmap has acceptable dimensions, call \c PixelMap::badSize().
01858          * To convert the bitmap dimensions to acceptable values, call \c PixelMap::rescale().
01859          * \param bmpFileName is the name of the file to be read, with the extension '.bmp'.
01860          */
01861         void read(char *bmpFileName);
01862 
01863         /**
01864          * Read a pixel map from a region of the framebuffer.
01865          * This function is similar to the constructor with the same parameters,
01866          * but allocates new memory only if necessary.
01867          * \param x is the \a X coordinate of the lower left corner of the region.
01868          * \param y is the \a Y coordinate of the lower left corner of the region.
01869          * \param w is the width of the region in pixels.
01870          * \param h is the height of the region in pixels.
01871          * \note See also the constructor PixelMap(x, y, w, h).
01872          */
01873         void read(GLint x, GLint y, GLsizei w, GLsizei h);
01874 
01875         /**
01876          * Write a pixel map to an output stream as a \a BMP file.
01877          * \param bmpFileName is the name of the file to be written, with the extension '.bmp'.
01878          */
01879         void write(char *bmpFileName);
01880 
01881         /**
01882          * Check the dimensions of the bit map.
01883          * If the dimensions are not powers of 2, return \c true.
01884          * If the dimensions of the bitmap are not powers of 2,
01885          * OpenGL cannot use it as a texture.
01886          * You should call \c PixelMap::rescale() to resize the bit map.
01887          */
01888         bool badSize();
01889 
01890         /**
01891          * Rescale a bit map whose dimensions are not powers of 2.
01892          * The new image will be distorted; the amount of distortion depends
01893          * on how much the dimensions have to be altered.
01894          * Use \c PixelMap::badSize() to determine whether the dimensions are powers of 2.
01895          */
01896         void rescale();
01897 
01898         /**
01899          * Draw the pixel map at the current raster position.
01900          * Error \c NO_PIX_MAP if there is no pixel map avaialble.
01901          */
01902         void draw();
01903 
01904         /**
01905          * Set texture parameters for the pixel map.
01906          * \param name is an OpenGL index for the texture parameters
01907          * provided by the caller.
01908          * \note This function sets \c GL_TEXTURE_MAG_FILTER and
01909          * \c GL_TEXTURE_MIN_FILTER to \c GL_NEAREST.  Call glTexParameter()
01910          * to change these settings.
01911          * \note When this function returns, OpenGL has copied the pixel map
01912          * into its own memory space.  It is therefore safe to delete the
01913          * PixelMap instance after calling setTexture().
01914          */
01915         void setTexture(GLuint name);
01916 
01917         /**
01918          * Set texture parameters for the pixel mipmaps.
01919          * Construct a family of mipmaps for texturing.
01920          * \param name is an OpenGL index for the texture parameters
01921          * provided by the caller.
01922          * \note This function sets \c GL_TEXTURE_MIN_FILTER to
01923          * \c GL_LINEAR_MIPMAP_NEAREST.  Call glTexParameter()
01924          * to change this setting.
01925          * \note When this function returns, OpenGL has copied the pixel map
01926          * into its own memory space.  It is therefore safe to delete the
01927          * PixelMap instance after calling setMipmaps().
01928          * \note Call this function once only for each texture you need in
01929          * your program.  Use \c glBindTexture to select textures in the
01930          * display function.
01931          */
01932         void setMipmaps(GLuint name);
01933 
01934         /** Check that two pixel maps are compatible for combining. */
01935         friend bool compatible(const PixelMap & m1, const PixelMap & m2);
01936 
01937         /** Combine two pixel maps.
01938          * \param m1 is the first map to be combined.
01939          * \param m2 is the second map to be combined.
01940          * \param res is the resulting pixel map.
01941                   The caller is responsible for constructing this map;
01942                   it is not constructed by the function.
01943            \param prop is the mixing proportion: 0 gives m1,
01944                   0.5 gives half of each, and 1 gives m2.
01945          */
01946         friend void mix(const PixelMap & m1, const PixelMap & m2, PixelMap & res, double prop);
01947 
01948         /** Select a region from a pixel map.
01949          * \param src is the pixel map from which the data is extracted.
01950          * \param xp defines the left side of the selected region.
01951          * \param yp defines the right side of the selected region.
01952          * \param width is the width of the selected region.
01953          * \param height is the height of the selected region.
01954          */
01955         void select(const PixelMap & src, int xp, int yp, int width, int height);
01956 
01957         /**
01958          * Return number of rows in pixel map.
01959          */
01960         unsigned long getRows() const
01961         {
01962             return numRows;
01963         }
01964 
01965         /**
01966          * Return number of columns in pixel map.
01967          */
01968         unsigned long getColumns() const
01969         {
01970             return numCols;
01971         }
01972 
01973         /**
01974          * Return bytes of memory used by pixel map.
01975          */
01976         unsigned long getSize() const
01977         {
01978             return size;
01979         }
01980 
01981         /**
01982          * Return name of BMP file.
01983          */
01984         char *getName() const
01985         {
01986             return fileName;
01987         }
01988 
01989         /**
01990          * Return \c true if a pixel map has been read successfully.
01991          */
01992         bool ready() const
01993         {
01994             return pixels != 0;
01995         }
01996 
01997         /**
01998          * Write a description of the pixel map to the output stream.
01999          */
02000         friend std::ostream & operator<<(std::ostream & os, PixelMap & pm);
02001 
02002     private:
02003 
02004         /**
02005          * The copy constructor is private and unimplemented.
02006          * This prevents pixel maps from being copied by mistake.
02007          */
02008         PixelMap(const PixelMap & pm);
02009 
02010         /** Allocate memory for a new pixel map if necessary. */
02011         bool allocate(unsigned long newSize);
02012 
02013         /** Number of rows in the pixel map. */
02014         unsigned long numRows;
02015 
02016         /** Number of columns in the pixel map. */
02017         unsigned long numCols;
02018 
02019         /** Size, in bytes, of the pixel map. */
02020         unsigned long size;
02021 
02022         /** Name of the file used to store the pixel map. */
02023         char *fileName;
02024 
02025         /** Pointer to the pixels of the map. */
02026         unsigned char *pixels;
02027     };
02028 
02029 
02030     /** The type of an array of GLfloats. */
02031     typedef GLfloat* GLfloatArray;
02032 
02033     /**
02034      * An instance is a surface of revolution represented by its profile.
02035 
02036      * The shape of the surface is determined by a 'profile'.
02037      *
02038      * The profile is defined by an array.  Each component of the
02039      * array is a pair \a (h,r) in which \a h is measured along
02040      * the axis of revolution and \a r is the distance from the
02041      * axis.  (If the axis is assumed to be vertical, then \a h
02042      * suggests 'height' and \a r suggests 'radius'.)
02043      * The surface is generated by rotating the profile
02044      * about the \a Z-axis.
02045      *
02046      * The function \c Revolute::draw() generates
02047      * vertex coordinates, normals, and texture coordinates for the
02048      * surface.
02049      *
02050      * It is up to the caller to set the OpenGL state for rendering:
02051      * this includes setting material properties and defining rules for polygon shading,
02052      * or binding an appropriate texture.
02053      *
02054      * The normals generated by \c Revolute::process() are obtained by averaging
02055      * the normals of the polygons that meet at each vertex.  Consequently,
02056      * if \c GL_SMOOTH shading is used and sufficient points and slices are specified,
02057      * the object should look fairly smooth.
02058      */
02059     class Revolute
02060     {
02061     public:
02062         /**
02063          * Construct a surface of revolution.
02064          *
02065          * \param numSteps is the number of coordinates in the profile.
02066          * \param profile is the address of a 2D array giving the points of the profile.
02067          */
02068         Revolute(int numSteps, GLfloat profile[][2]);
02069 
02070         /**
02071          * Delete a surface of revolution.
02072          */
02073         ~Revolute();
02074 
02075         /**
02076          * Set the number of "slices".
02077          * The value determines the visual quality of the object.
02078          * The number of slices should be an odd number greater than 2.
02079          * If it is not, Revolute::process() will change it.
02080          * By default, the number of slices is 45, corresponding to
02081          * 8 degrees per slice.
02082          * \note After changing the number of slices, you must call
02083          * \c Revolute::process() again before calling \c Revolute::draw().
02084          */
02085         void setSlices(int slices);
02086 
02087         /**
02088          * Set the eccentricity of the surface.
02089          * By default, the eccentricity is 0, giving a surface
02090          * with a circular cross-section.  Setting the eccentricity
02091          * to a non-zero value gives a surface with an elliptical
02092          * cross-section.  As the eccentricity approaches 1,
02093          * the major axis of the ellipse increases without limit
02094          * as the cross-section approaches a parabola.
02095          * \param ecc must be greater than or equal to zero and
02096          * less than 1.
02097          * \note After changing the eccentricity, you must call
02098          * \c Revolute::process() again before calling \c Revolute::draw().
02099          */
02100         void setEccentricity(double ecc);
02101 
02102         /**
02103          * Compute vertexes, normals, and texture coordinates for the surface of revolution.
02104          * This function must be called \b before calling \c Revolute::draw().
02105          */
02106         void process();
02107 
02108         /**
02109          * Draw the surface of revolution.
02110          * \param showNormals determines whether surface normals will be drawn.
02111          * Note that surface normals are computed for lighting purposes anyway:
02112          * \c showNormals is provided mainly as a debugging aid and should not
02113          * normally be needed.
02114          * \note Revolute::process() must be called before this function.
02115          */
02116         void draw(bool showNormals = false);
02117 
02118     private:
02119 
02120         /**
02121          * The copy constructor is private and not implemented:
02122          * instances cannot be copied implicitly.
02123          */
02124         Revolute::Revolute(const Revolute&);
02125 
02126         /**
02127          * The assignment operator is private and not implemented:
02128          * instances cannot be assigned.
02129          */
02130         const Revolute& Revolute::operator=(const Revolute&);
02131 
02132         /** */
02133         int numSteps;
02134 
02135         /** */
02136         int numSlices;
02137 
02138         /** */
02139         double eccentricity;
02140 
02141         /** */
02142         bool ready;
02143 
02144         /** */
02145         GLfloatArray *coor;
02146 
02147         /** */
02148         GLfloat *texCoor;
02149 
02150         /** */
02151         Point *points;
02152 
02153         /** */
02154         Vector *normals;
02155 
02156         /** */
02157         Vector *faceNormals;
02158     };
02159 
02160 
02161     /**
02162      * \defgroup freefun Miscellaneous functions
02163      */
02164 
02165     //@{
02166 
02167     /**
02168      * Convert degrees to radians.
02169      */
02170     inline double radians(double angle)
02171     {
02172         return angle * PI / 180;
02173     }
02174 
02175     /**
02176      * Convert radians to degrees.
02177      */
02178     inline double degrees(double angle)
02179     {
02180         return angle * 180 / PI;
02181     }
02182 
02183     /**
02184      * Construct normals for OpenGL triangle strips.
02185      * Given a set of vertexes definining a triangle strip in OpenGL format,
02186      * this functions constructs a normal corresponding to each vertex.
02187      * \param points is an array of points giving the vertex coordinates.
02188      * \param normals is an array of vectors in which the vertex normals will be stored.
02189      * \param numPoints is the number of vertexes provided and the number of normals
02190      * that will be calculated.
02191      * \param neg specifies negated normals, if \a true.
02192               The default is \a false.
02193      * \note To avoid allocation and deallocation overhead, this function uses a
02194      * a fixed amount of workspace that allows up to 100 vertexes to be processed.
02195      * If numPoints > 100, the function will have no effect.
02196      * \note For efficiency, it is better to compute the normals during initialization
02197      * rather than each time the model is displayed.
02198      */
02199     void triStripNormals(Point points[], Vector normals[], int numPoints, bool neg = false);
02200 
02201     /**
02202      * Constructs a surface of revolution.
02203      * Constructs and renders a surface of revolution obtained by rotating
02204      * a curve about the \a Y axis.
02205 
02206      * \param numSteps is the number of points in the array \c coor
02207      * \param coor is the 2D coordinates of points of the profile
02208      * \param numSlices is the number of pie-shaped slices used to render the surface.
02209      * \param drawNormals determines whether normals are generated.  By default, normals
02210      *        are not generated.
02211 
02212      * For example, if \c numSlices = 20, points will be constructed at 360/20 = 18
02213      * degree intervals.
02214 
02215      * This function constructs an array of points in 3D space and then issues
02216      * calls to \c glVertex().  If \c drawNormals is true, it also issues calls to
02217      * \c glNormal().  The effect of these calls is to define a 3D mesh.
02218      * It is up to the caller to set the OpenGL state for rendering:
02219      * this includes setting material properties and defining rules for polygon shading.
02220 
02221      * The normals generated by \c revolve() are obtained by averaging the normals of the
02222      * polygons that meet at each vertex.  Consequently, if \c GL_SMOOTH shading is used
02223      * and enough points are specified, the object should look fairly smooth.
02224 
02225      * \note This function has been replaced by class \c Revolute, which provides more
02226      * functionality and is more efficient.
02227      */
02228     void revolve(int numSteps, GLfloat coor[][2], int numSlices, bool drawNormals = false);
02229 
02230 
02231 
02232     // Additional inline functions for Point and Vector classes.
02233 
02234     /**
02235      * Call gluLookAt() looking at the origin of the model (0,0,0)
02236      * with 'up' vector (0,1,0).
02237      * \param eye is the position of the viewer's eye.
02238      */
02239     inline void lookAt(Point eye)
02240     {
02241         gluLookAt
02242         (
02243             eye[0], eye[1], eye[2],
02244             0, 0, 0,
02245             0, 1, 0
02246         );
02247     }
02248 
02249     /**
02250      * Call gluLookAt() with 'up' vector (0,1,0).
02251      * \param eye is the position of the viewer's eye in model coordinates.
02252      * \param model is the point at the centre of the view in model coordinates.
02253      */
02254     inline void lookAt(Point eye, Point model)
02255     {
02256         gluLookAt
02257         (
02258             eye[0], eye[1], eye[2],
02259             model[0], model[1], model[2],
02260             0, 1, 0
02261         );
02262     }
02263 
02264     /**
02265      * Call gluLookAt().
02266      * \param eye is the position of the viewer's eye in model coordinates.
02267      * \param model is the point at the centre of the view in model coordinates.
02268      * \param up is a vector giving the upwards direction in the model.
02269      */
02270     inline void lookAt(Point eye, Point model, Vector up)
02271     {
02272         gluLookAt
02273         (
02274             eye[0], eye[1], eye[2],
02275             model[0], model[1], model[2],
02276             up[0], up[1], up[2]
02277         );
02278     }
02279 
02280     // End of free functions
02281     //@}
02282 
02283 
02284     /**
02285      * \defgroup model Materials and Models
02286      */
02287 
02288     //@{
02289 
02290     /**
02291      * \todo Models should probably be put into a separate file.
02292      */
02293 
02294     // Axes
02295 
02296     /**
02297      * Draw coordinate axes.
02298      * This function draws the three principal axes in the current
02299      * position, using \c size to determine the length of each axis.
02300      * The axes are colour-coded: \a X = red, \a Y = green, \a Z = blue.
02301      */
02302     void axes(GLfloat size = 1);
02303 
02304     /**
02305      * Draw an aircraft.
02306      * The argument determines whether the plane is drawn with a metallic
02307      * colour (\c shadow = \c false, the default) or black, to act as a
02308      * shadow (\c shadow = \c true).
02309      * The aircraft is built using Bezier surfaces. If you use glScalef
02310      * to change its size, you must enable \c GL_NORMALIZE to correct
02311      * the normals. Otherwise, the lighting will be wrong.
02312      */
02313     void buildPlane(bool shadow = false);
02314 
02315     /**
02316      * Construct a GL call list for the aircraft and return its index.
02317      */
02318     GLuint makePlaneList(bool shadow = false);
02319 
02320 
02321     /**
02322      * Enumeration for materials.
02323      */
02324     enum MATERIAL
02325     {
02326         BLACK,            /**< Black. */
02327         WHITE,            /**< White. */
02328         RED,              /**< Red. */
02329         GREEN,            /**< Green. */
02330         BLUE,             /**< Blue. */
02331         METAL,            /**< General metallic colour.*/
02332         GLASS,            /**< General transparent marterial.*/
02333         BRASS,            /**< Brass. */
02334         BRONZE,           /**< Matt bronze. */
02335         POLISHED_BRONZE,  /**< Polished bronze. */
02336         CHROME,           /**< Chrome. */
02337         COPPER,           /**< Matt copper. */
02338         POLISHED_COPPER,  /**< Polished copper. */
02339         GOLD,             /**< Matt gold. */
02340         POLISHED_GOLD,    /**< Polished gold. */
02341         PEWTER,           /**< Pewter. */
02342         SILVER,           /**< Matt silver. */
02343         POLISHED_SILVER,  /**< Polished silver. */
02344         EMERALD,          /**< Emerald. */
02345         JADE,             /**< Jade. */
02346         OBSIDIAN,         /**< Obsidian. */
02347         PEARL,            /**< Pearl. */
02348         RUBY,             /**< Ruby. */
02349         TURQUOISE,        /**< Turquoise. */
02350         BLACK_PLASTIC,    /**< Black plastic. */
02351         BLACK_RUBBER,      /**< Black rubber. */
02352         LAST_VALUE
02353     };
02354 
02355     /**
02356      * Set material values from the enumeration.
02357      \param m is chosen from the enumeration \c MATERIAL
02358      \param face should be one of \c GL_FRONT (the default),
02359      \c GL_BACK, or \c GL_FRONT_AND_BACK.
02360      */
02361     void setMaterial(const int m, GLenum face = GL_FRONT);
02362 
02363     // The following array describes material properties.
02364     //    ambiance  [4],
02365     //    diffuse   [4],
02366     //    specular  [4],
02367     //    shininess [1].
02368     // 13 values are required to define a material.
02369 
02370     /**
02371      * Add a material to the set of built-in materials.
02372      * The array of material has a fixed size of 100.
02373      * An attempt to create more than 100 materials will fail.
02374      * The parameters specify:
02375      *
02376      * - RGBA values for ambient light
02377      * - RGBA values for diffuse light
02378      * - RGBA values for specular light
02379      * - Value for shininess exponent
02380      * \return the index of the new material.
02381      */
02382     int addMaterial(
02383         GLfloat ambR, GLfloat ambG, GLfloat ambB, GLfloat ambA,
02384         GLfloat difR, GLfloat difG, GLfloat difB, GLfloat difA,
02385         GLfloat speR, GLfloat speG, GLfloat speB, GLfloat speA,
02386         GLfloat shine);
02387 
02388     /**
02389      * Add a material to the set of built-in materials.
02390      * The array of material has a fixed size of 100.
02391      * An attempt to create more than 100 materials will fail.
02392      * \param params specifies:
02393      * - RGBA values for ambient light
02394      * - RGBA values for diffuse light
02395      * - RGBA values for specular light
02396      * - Value for shininess exponent
02397      * \return the index of the new material.
02398      */
02399     int addMaterial(GLfloat params[]);
02400 
02401     // End of free functions
02402     //@}
02403 
02404     //=============================== End of declarations ==============================//
02405 
02406     // Code below this point consists of inline function definitions.
02407     // Functions that are not defined here are defined in cugl.cpp.
02408 
02409     // class Point: inlined constructors and member functions.
02410 
02411     inline Point::Point (GLfloat coordinates[])
02412     {
02413         x = coordinates[0];
02414         y = coordinates[1];
02415         z = coordinates[2];
02416         w = coordinates[3];
02417     }
02418 
02419     inline Point Point::operator+=(const Vector & v)
02420     {
02421         x += w * v.x;
02422         y += w * v.y;
02423         z += w * v.z;
02424         return *this;
02425     }
02426 
02427     inline Point Point::operator-=(const Vector & v)
02428     {
02429         x -= w * v.x;
02430         y -= w * v.y;
02431         z -= w * v.z;
02432         return *this;
02433     }
02434 
02435     inline Point Point::operator/(GLfloat s) const
02436     {
02437         return Point(x, y, z, s * w);
02438     }
02439 
02440     inline void Point::draw() const
02441     {
02442         if (w == 0)
02443             return;
02444         glVertex4f(x, y, z, w);
02445     }
02446 
02447     inline void Point::light(GLenum lightNum) const
02448     {
02449         GLfloat p[4];
02450         p[0] = x;
02451         p[1] = y;
02452         p[2] = z;
02453         p[3] = w;
02454         glLightfv(lightNum, GL_POSITION, p);
02455     }
02456 
02457     inline void Point::translate() const
02458     {
02459         glTranslatef(x/w, y/w, z/w);
02460     }
02461 
02462     // class Point: inlined friend functions.
02463 
02464     inline Point operator+(const Point & p, const Vector & v)
02465     {
02466         return Point(p.x + p.w * v.x, p.y + p.w * v.y, p.z + p.w * v.z, p.w);
02467     }
02468 
02469     inline Point operator+(const Vector & v, const Point & p)
02470     {
02471         return Point(p.x + p.w * v.x, p.y + p.w * v.y, p.z + p.w * v.z, p.w);
02472     }
02473 
02474     inline Point operator*(const Point & p, GLfloat s)
02475     {
02476         return Point(s * p.x, s * p.y, s * p.z, s * p.w);
02477     }
02478 
02479     inline Point operator*(GLfloat s, const Point & p)
02480     {
02481         return Point(s * p.x, s * p.y, s * p.z, s * p.w);
02482     }
02483 
02484     inline bool operator==(const Point & p, const Point & q)
02485     {
02486         return p.x == q.x && p.y == q.y && p.z == q.z && p.w == q.w;
02487     }
02488 
02489     inline bool operator!=(const Point & p, const Point & q)
02490     {
02491         return !(p == q);
02492     }
02493 
02494     inline GLfloat dist(const Point & p, const Plane & s)
02495     {
02496         return p.x * s.a + p.y * s.b + p.z * s.c + p.w * s.d;
02497     }
02498 
02499     inline GLfloat dist(const Plane & s, const Point & p)
02500     {
02501         return s.a * p.x + s.b * p.y + s.c * p.z + s.d * p.w;
02502     }
02503 
02504     // Class Line: inlined member functions.
02505 
02506     inline Line::Line(Point & p, Point & q)
02507             : s(p), f(q)
02508     { }
02509 
02510     inline Line::Line(Point & p, Vector & v)
02511             : s(p), f(p + v)
02512     { }
02513 
02514 
02515     // Class Line: inlined friend functions.
02516 
02517     inline bool operator==(const Line & m, const Line & n)
02518     {
02519         return m.s == n.s && m.f == n.f;
02520     }
02521 
02522     inline bool operator!=(const Line & m, const Line & n)
02523     {
02524         return !(m == n);
02525     }
02526 
02527 
02528 
02529     // Class Plane: inlined member functions.
02530 
02531     inline Vector Plane::normal() const
02532     {
02533         return Vector(a,b,c).unit();
02534     }
02535 
02536     // Class Plane: inlined friend functions.
02537 
02538     inline bool operator==(const Plane & p, const Plane & q)
02539     {
02540         return p.a == q.a && p.b == q.b && p.c == q.c && p.d == q.d;
02541     }
02542 
02543     inline bool operator!=(const Plane & p, const Plane & q)
02544     {
02545         return !(p == q);
02546     }
02547 
02548 
02549 
02550     // class Vector: inlined constructors
02551 
02552     inline Vector::Vector (GLfloat coordinates[])
02553     {
02554         x = coordinates[0];
02555         y = coordinates[1];
02556         z = coordinates[2];
02557     }
02558 
02559     inline Vector::Vector(Point & p, Point & q)
02560     {
02561         if (p.w == 0 || q.w == 0)
02562         {
02563             x = 0;
02564             y = 0;
02565             z = 0;
02566         }
02567         else
02568         {
02569             x = p.x/p.w - q.x/q.w;
02570             y = p.y/p.w - q.y/q.w;
02571             z = p.z/p.w - q.z/q.w;
02572         }
02573     }
02574 
02575     inline Vector::Vector(const Quaternion & q)
02576     {
02577         x = q.v.x;
02578         y = q.v.y;
02579         z = q.v.z;
02580     }
02581 
02582     // class Vector: inlined member functions.
02583 
02584     inline Vector Vector::operator+=(const Vector & v)
02585     {
02586         x += v.x;
02587         y += v.y;
02588         z += v.z;
02589         return *this;
02590     }
02591 
02592     inline Vector Vector::operator-=(const Vector & v)
02593     {
02594         x -= v.x;
02595         y -= v.y;
02596         z -= v.z;
02597         return *this;
02598     }
02599 
02600     inline Vector Vector::operator-() const
02601     {
02602         return Vector(-x, -y, -z);
02603     }
02604 
02605     inline Vector Vector::operator*=(GLfloat scale)
02606     {
02607         x *= scale;
02608         y *= scale;
02609         z *= scale;
02610         return *this;
02611     }
02612 
02613     inline GLfloat Vector::norm() const
02614     {
02615         return x * x + y * y + z * z;
02616     }
02617 
02618     inline GLfloat Vector::length() const
02619     {
02620         return GLfloat(sqrt(norm()));
02621     }
02622 
02623     inline void Vector::translate() const
02624     {
02625         glTranslatef(x, y, z);
02626     }
02627 
02628     inline void Vector::drawNormal() const
02629     {
02630         glNormal3f(x, y, z);
02631     }
02632 
02633     inline void Vector::draw(const Point & p) const
02634     {
02635         glBegin(GL_LINES);
02636         p.draw();
02637         (p + (*this)).draw();
02638         glEnd();
02639     }
02640 
02641     // class Vector: inlined friend functions.
02642 
02643     inline Vector operator-(const Point & p, const Point & q)
02644     {
02645         if (p.w == 0 || q.w == 0)
02646             return Vector();
02647         else
02648             return Vector(p.x/p.w - q.x/q.w, p.y/p.w - q.y/q.w, p.z/p.w - q.z/q.w);
02649     }
02650 
02651     inline Vector operator+(const Vector & u, const Vector & v)
02652     {
02653         return Vector(u.x + v.x, u.y + v.y, u.z + v.z);
02654     }
02655 
02656     inline Vector operator-(const Vector & u, const Vector & v)
02657     {
02658         return Vector(u.x - v.x, u.y - v.y, u.z - v.z);
02659     }
02660 
02661     inline Vector operator*(const Vector & v, GLfloat s)
02662     {
02663         return Vector(s * v.x, s * v.y, s * v.z);
02664     }
02665 
02666     inline Vector operator*(GLfloat s, const Vector & v)
02667     {
02668         return Vector(s * v.x, s * v.y, s * v.z);
02669     }
02670 
02671     inline Vector cross(const Vector & u, const Vector & v)
02672     {
02673         return Vector(
02674                    u.y * v.z - u.z * v.y,
02675                    u.z * v.x - u.x * v.z,
02676                    u.x * v.y - u.y * v.x );
02677     }
02678 
02679     inline Vector operator*(const Vector & u, const Vector & v)
02680     {
02681         return Vector(
02682                    u.y * v.z - u.z * v.y,
02683                    u.z * v.x - u.x * v.z,
02684                    u.x * v.y - u.y * v.x );
02685     }
02686 
02687     inline GLfloat dot(const Vector & u, const Vector & v)
02688     {
02689         return u.x * v.x + u.y * v.y + u.z * v.z;
02690     }
02691 
02692     inline bool operator==(const Vector & u, const Vector & v)
02693     {
02694         return u.x == v.x && u.y == v.y && u.z == v.z;
02695     }
02696 
02697     inline bool operator!=(const Vector & u, const Vector & v)
02698     {
02699         return !(u == v);
02700     }
02701 
02702 
02703 
02704     // Class Matrix: inlined constructors
02705 
02706     inline Matrix::Matrix(const Plane & p)
02707     {
02708         reflect(p);
02709     }
02710 
02711     inline Matrix::Matrix(const Point & lightPos, const Plane & plane)
02712     {
02713         shadow(lightPos, plane);
02714     }
02715 
02716     // Class Matrix: inlined member functions
02717 
02718     inline Point Matrix::apply(const Point & p) const
02719     {
02720         return Point
02721                (
02722                    m[0][0] * p.x + m[0][1] * p.y + m[0][2] * p.z + m[0][3] * p.w,
02723                    m[1][0] * p.x + m[1][1] * p.y + m[1][2] * p.z + m[1][3] * p.w,
02724                    m[2][0] * p.x + m[2][1] * p.y + m[2][2] * p.z + m[2][3] * p.w,
02725                    m[3][0] * p.x + m[3][1] * p.y + m[3][2] * p.z + m[3][3] * p.w
02726                );
02727     }
02728 
02729     inline void Matrix::apply() const
02730     {
02731         glMultMatrixf(&m[0][0]);
02732     }
02733 
02734     inline GLfloat *Matrix::get()
02735     {
02736         return &m[0][0];
02737     }
02738 
02739     inline GLfloat & Matrix::operator()(int i, int j)
02740     {
02741         return m[i][j];
02742     }
02743 
02744     inline const GLfloat & Matrix::operator()(int i, int j) const
02745     {
02746         return m[i][j];
02747     }
02748 
02749     inline Matrix Matrix::operator~() const
02750     {
02751         return inv();
02752     }
02753 
02754     inline Vector Matrix::apply(const Vector & v) const
02755     {
02756         // Gives same result as quaternion.
02757         return Vector
02758                (
02759                    m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2],
02760                    m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2],
02761                    m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2]
02762                );
02763     }
02764 
02765     // Class Matrix: inlined friend functions
02766 
02767     inline Matrix operator*(const Matrix & m, const Matrix & n)
02768     {
02769         Matrix r;
02770         r(0,0) = m(0,0) * n(0,0) + m(0,1) * n(1,0) + m(0,2) * n(2,0) + m(0,3) * n(3,0);
02771         r(0,1) = m(0,0) * n(0,1) + m(0,1) * n(1,1) + m(0,2) * n(2,1) + m(0,3) * n(3,1);
02772         r(0,2) = m(0,0) * n(0,2) + m(0,1) * n(1,2) + m(0,2) * n(2,2) + m(0,3) * n(3,2);
02773         r(0,3) = m(0,0) * n(0,3) + m(0,1) * n(1,3) + m(0,2) * n(2,3) + m(0,3) * n(3,3);
02774         r(1,0) = m(1,0) * n(0,0) + m(1,1) * n(1,0) + m(1,2) * n(2,0) + m(1,3) * n(3,0);
02775         r(1,1) = m(1,0) * n(0,1) + m(1,1) * n(1,1) + m(1,2) * n(2,1) + m(1,3) * n(3,1);
02776         r(1,2) = m(1,0) * n(0,2) + m(1,1) * n(1,2) + m(1,2) * n(2,2) + m(1,3) * n(3,2);
02777         r(1,3) = m(1,0) * n(0,3) + m(1,1) * n(1,3) + m(1,2) * n(2,3) + m(1,3) * n(3,3);
02778         r(2,0) = m(2,0) * n(0,0) + m(2,1) * n(1,0) + m(2,2) * n(2,0) + m(2,3) * n(3,0);
02779         r(2,1) = m(2,0) * n(0,1) + m(2,1) * n(1,1) + m(2,2) * n(2,1) + m(2,3) * n(3,1);
02780         r(2,2) = m(2,0) * n(0,2) + m(2,1) * n(1,2) + m(2,2) * n(2,2) + m(2,3) * n(3,2);
02781         r(2,3) = m(2,0) * n(0,3) + m(2,1) * n(1,3) + m(2,2) * n(2,3) + m(2,3) * n(3,3);
02782         r(3,0) = m(3,0) * n(0,0) + m(3,1) * n(1,0) + m(3,2) * n(2,0) + m(3,3) * n(3,0);
02783         r(3,1) = m(3,0) * n(0,1) + m(3,1) * n(1,1) + m(3,2) * n(2,1) + m(3,3) * n(3,1);
02784         r(3,2) = m(3,0) * n(0,2) + m(3,1) * n(1,2) + m(3,2) * n(2,2) + m(3,3) * n(3,2);
02785         r(3,3) = m(3,0) * n(0,3) + m(3,1) * n(1,3) + m(3,2) * n(2,3) + m(3,3) * n(3,3);
02786         return r;
02787     }
02788 
02789     inline bool operator==(const Matrix & m, const Matrix & n)
02790     {
02791         for (int i = 0; i < 4; i++)
02792             for (int j = 0; j < 4; j++)
02793                 if (m(i,j) != n(i,j))
02794                     return false;
02795         return true;
02796     }
02797 
02798     inline bool operator!=(const Matrix & m, const Matrix & n)
02799     {
02800         for (int i = 0; i < 4; i++)
02801             for (int j = 0; j < 4; j++)
02802                 if (m(i,j) != n(i,j))
02803                     return true;
02804         return false;
02805     }
02806 
02807 
02808 
02809     // Class Quaternion: inlined member functions.
02810 
02811     inline Vector Quaternion::apply(const Vector & w) const
02812     {
02813         return Vector
02814                (
02815                    -(-w[0] * v[0] - w[1] * v[1] - w[2] * v[2]) * v[0] + s * (s * w[0] + w[1] * v[2] - w[2] * v[1])
02816                    - v[1] * (s * w[2] + w[0] * v[1] - w[1] * v[0]) + v[2] * (s * w[1] + w[2] * v[0] - w[0] * v[2]),
02817                    -(-w[0] * v[0] - w[1] * v[1] - w[2] * v[2]) * v[1] + s * (s * w[1] + w[2] * v[0] - w[0] * v[2])
02818                    - v[2] * (s * w[0] + w[1] * v[2] - w[2] * v[1]) + v[0] * (s * w[2] + w[0] * v[1] - w[1] * v[0]),
02819                    -(-w[0] * v[0] - w[1] * v[1] - w[2] * v[2]) * v[2] + s * (s * w[2] + w[0] * v[1] - w[1] * v[0])
02820                    - v[0] * (s * w[1] + w[2] * v[0] - w[0] * v[2]) + v[1] * (s * w[0] + w[1] * v[2] - w[2] * v[1])
02821                );
02822     }
02823 
02824     inline Vector Quaternion::vector() const
02825     {
02826         return v;
02827     }
02828 
02829     inline GLfloat Quaternion::scalar() const
02830     {
02831         return s;
02832     }
02833 
02834     inline GLfloat Quaternion::norm() const
02835     {
02836         return s * s + v.norm();
02837     }
02838 
02839     inline GLfloat Quaternion::magnitude() const
02840     {
02841         return GLfloat(sqrt(norm()));
02842     }
02843 
02844     inline Quaternion Quaternion::conj() const
02845     {
02846         return Quaternion(s, -v);
02847     }
02848 
02849     inline Vector Quaternion::axis() const
02850     {
02851         return v.unit();
02852     }
02853 
02854     inline double Quaternion::angle() const
02855     {
02856         return 2 * acos(s);
02857     }
02858 
02859     inline Quaternion Quaternion::operator~() const
02860     {
02861         return inv();
02862     }
02863 
02864     inline Quaternion Quaternion::operator*=(const Quaternion & q)
02865     {
02866         GLfloat ns = s * q.s - v[0] * q.v[0] - v[1] * q.v[1] - v[2] * q.v[2];
02867         v = Vector(
02868                 q.s * v[0] + s * q.v[0] + v[1] * q.v[2] - v[2] * q.v[1],
02869                 q.s * v[1] + s * q.v[1] + v[2] * q.v[0] - v[0] * q.v[2],
02870                 q.s * v[2] + s * q.v[2] + v[0] * q.v[1] - v[1] * q.v[0] );
02871         s = ns;
02872         return *this;
02873 
02874     }
02875 
02876     // class Quaternion: inlined friend functions.
02877 
02878     inline GLfloat dot(const Quaternion & q, const Quaternion & r)
02879     {
02880         return q.s * r.s + dot(q.v, r.v);
02881     }
02882 
02883     inline Quaternion operator+(const Quaternion & q, const Quaternion & r)
02884     {
02885         return Quaternion(q.s + r.s, q.v + r.v);
02886     }
02887 
02888     inline Quaternion operator-(const Quaternion & q, const Quaternion & r)
02889     {
02890         return Quaternion(q.s - r.s, q.v - r.v);
02891     }
02892 
02893     inline Quaternion operator*(const Quaternion & q, const Quaternion & r)
02894     {
02895         return Quaternion
02896                (
02897                    q.s * r.s - q.v[0] * r.v[0] - q.v[1] * r.v[1] - q.v[2] * r.v[2],
02898                    r.s * q.v[0] + q.s * r.v[0] + q.v[1] * r.v[2] - q.v[2] * r.v[1],
02899                    r.s * q.v[1] + q.s * r.v[1] + q.v[2] * r.v[0] - q.v[0] * r.v[2],
02900                    r.s * q.v[2] + q.s * r.v[2] + q.v[0] * r.v[1] - q.v[1] * r.v[0]
02901                );
02902     }
02903 
02904     inline Quaternion operator*(const Vector & v, const Quaternion & q)
02905     {
02906         return Quaternion
02907                (
02908                    - v[0] * q.v[0] - v[1] * q.v[1] - v[2] * q.v[2],
02909                    q.s * v[0] +   v[1] * q.v[2] - v[2] * q.v[1],
02910                    q.s * v[1] +   v[2] * q.v[0] - v[0] * q.v[2],
02911                    q.s * v[2] +   v[0] * q.v[1] - v[1] * q.v[0]
02912                );
02913     }
02914 
02915     inline Quaternion operator*(const Quaternion & q, const Vector & v)
02916     {
02917         return Quaternion
02918                (
02919                    - q.v[0] * v[0] - q.v[1] * v[1] - q.v[2] * v[2],
02920                    q.s * v[0] + q.v[1] * v[2] - q.v[2] * v[1],
02921                    q.s * v[1] + q.v[2] * v[0] - q.v[0] * v[2],
02922                    q.s * v[2] + q.v[0] * v[1] - q.v[1] * v[0]
02923                );
02924     }
02925 
02926     inline Quaternion operator/(const Quaternion & q, const Quaternion & r)
02927     {
02928         GLfloat den = r.norm();
02929         return Quaternion
02930                (
02931                    (q.s * r.s + q.v[0] * r.v[0] + q.v[1] * r.v[1] + q.v[2] * r.v[2]) / den,
02932                    (r.s * q.v[0] - q.s * r.v[0] - q.v[1] * r.v[2] + q.v[2] * r.v[1]) / den,
02933                    (r.s * q.v[1] - q.s * r.v[1] - q.v[2] * r.v[0] + q.v[0] * r.v[2]) / den,
02934                    (r.s * q.v[2] - q.s * r.v[2] - q.v[0] * r.v[1] + q.v[1] * r.v[0]) / den
02935                );
02936     }
02937 
02938     inline Quaternion Quaternion::operator/=(const Quaternion & q)
02939     {
02940         GLfloat den = q.norm();
02941         GLfloat ns = (s * q.s + v[0] * q.v[0] + v[1] * q.v[1] + v[2] * q.v[2]) / den;
02942         v = Vector
02943             (
02944                 (q.s * v[0] - s * q.v[0] - v[1] * q.v[2] + v[2] * q.v[1]) / den,
02945                 (q.s * v[1] - s * q.v[1] - v[2] * q.v[0] + v[0] * q.v[2]) / den,
02946                 (q.s * v[2] - s * q.v[2] - v[0] * q.v[1] + v[1] * q.v[0]) / den
02947             );
02948         s = ns;
02949         return *this;
02950     }
02951 
02952     inline Quaternion operator*(const Quaternion & q, GLfloat a)
02953     {
02954         return Quaternion(a * q.s, a * q.v);
02955     }
02956 
02957     inline Quaternion operator*(GLfloat a, const Quaternion & q)
02958     {
02959         return Quaternion(a * q.s, a * q.v);
02960     }
02961 
02962     inline bool operator==(const Quaternion & q, const Quaternion & r)
02963     {
02964         return q.s == r.s && q.v == r.v;
02965     }
02966 
02967     inline bool operator!=(const Quaternion & q, const Quaternion & r)
02968     {
02969         return !(q == r);
02970     }
02971 
02972 
02973 
02974     // class Interpolator: inline member functions
02975 
02976     inline void Interpolator::getMatrix(double t, GL_Matrix m) const
02977     {
02978         getQuaternion(t).matrix(m);
02979     }
02980 
02981 }
02982 ; // end of namespace
02983 
02984 #endif
02985 
02986 

Generated on Wed Sep 12 14:31:41 2007 for CUGL by  doxygen 1.5.2