CUGL  2.0
cugl.h
Go to the documentation of this file.
1 #ifndef CUGL_H
2 #define CUGL_H
3 
4 /** \file cugl.h
5  * Concordia University Graphics Library
6  *
7  * \authors Peter Grogono
8 */
9 
10 /** \mainpage Introduction
11 
12  The \c operator<< overloads for classes Point, Quaternion, and Matrix
13  use the current settings of format parameters. \c setw() determines
14  the width of each number rather than the entire field width.
15 
16  Most of the classes do not have copy constructors or \c operator= overloads
17  because the default versions generated by the compiler do the right
18  thing (for once). (Class PixelMap is an exception, because it has
19  pointer members.)
20 
21  \c GLfloat is used as the representation type for most floating-point values.
22  This is for compatibility with OpenGL. Although OpenGL provides a choice of
23  precision for vertex and normal data, matrices are provided in \c GLfloat form only.
24  Single-precision floating-point provides only about six decimal places, but this
25  is sufficient for most graphics calculations. If the number of points, vectors,
26  or matrices used is large, substantial amounts of memory may be saved.
27 
28  Acknowledgements: Mark Kilgard, Ken Shoemake, F.S. Hill, and others, for
29  various publications on mthematical techniques for graphics and OpenGL, and to
30  Liping Ye for improving various features, especially bitmaps.
31 */
32 
33 /** Extensions
34  * \todo Quaternion += and -=
35  * \todo Matrix operator*=(Matrix) - done
36  * \todo bool isVisible(Point) - harder than it looks
37  */
38 
39 #include <GL/glu.h>
40 #include <iostream>
41 #include <cmath>
42 
43 namespace cugl
44 {
45 
46 /** \defgroup constants Constants */
47 
48 //@{
49 
50 /** A string giving the version of CUGL and the most recent build date. */
51 const char version[] = "CUGL V2 2009.11.24";
52 
53 /** A well-known mathematical constant. */
54 const double PI = 4 * atan(1.0);
55 
56 // End of constants
57 //@}
58 
59 /** The type of OpenGL projection and model view matrices.
60  * It is tempting to write CUGL as a template llibrary, but the fixed type
61  * of OpenGL matrices makes this difficult to do effectively. */
62 typedef GLfloat GL_Matrix[4][4];
63 
64 /** \defgroup errors Error messages */
65 
66 //@{
67 
68 /** Enumeration values for CUGL function errors. */
70 {
71  NO_ERROR = 0, /**< No error has occurred since the error flag was reset. */
72  BAD_INDEX, /**< Encountered an invalid array index. */
73  BAD_MATRIX_MODE, /**< The matrix mode was not GL_PROJECTION or GL_MODELVIEW. */
74  BAD_ROTATION_MATRIX, /**< The given matrix was not a rotation matrix. */
75  SINGULAR_MATRIX, /**< The matrix is singular. */
76  ZERO_DIVISOR, /**< An attempt was made to divide by zero. */
77  ZERO_NORM, /**< An attempt was made to normalize a null vector. */
78  BAD_INTERPOLATOR_ARG, /**< The angle between the rotations of the interpolator is zero. */
79  OPEN_FAILED, /**< The program failed to open a BMP file. */
80  NOT_BMP_FILE, /**< The file opened was not a BMP file. */
81  NOT_24_BITS, /**< The BMP file was not in 24-bit format. */
82  COMPRESSED_BMP_FILE, /**< The BMP file was in compressed form. */
83  NOT_ENOUGH_MEMORY, /**< There is not enough memory to store the pixel map. */
84  NO_PIX_MAP, /**< There is no pixel map to draw. */
85  BAD_PLANE, /**< Parameters do not define a plane. */
86  BAD_LINE, /**< The line lies in the plane. */
87  TOO_MANY_MATERIALS, /**< Too many materials. */
88  TOO_MANY_POINTS /**< Too many points. */
89 };
90 
91 /**
92  * Set code to \c NO_ERROR and return last error code.
93  * \return the most recent error code.
94  */
96 
97 /** Map error codes to descriptive strings.
98  * \param err is an error code obtained from \c getError().
99  * \return A string describing the eeror.
100  */
101 const char *getErrorString(CUGLErrorType err);
102 
103 /**
104  * Display a message if an CUGL error has occurred.
105  * This function checks the CUGL error status.
106  * If no error has occurred, it has no effect.
107  * If CUGL has reported an error, this function writes
108  * the CUGL error code and the corresponding message
109  * to the stream \c cerr.
110  *
111  * Since \c getError() clears the CUGL error flag,
112  * after calling this function CUGL shows no errors.
113  *
114  * This function is intended mainly for development and
115  * should not normally be included in a production program.
116  */
117 void checkCUGLStatus();
118 
119 /**
120  * Display a message if an OpenGL error has occurred.
121  * This function checks the OpenGL error status.
122  * If no error has occurred, it has no effect.
123  * If OpenGL has reported an error, this function writes
124  * the OpenGL error code and the corresponding message
125  * to the stream \c cerr.
126  *
127  * Since \c glGetError() clears the OpenGL error flag,
128  * after calling this function OpenGL shows no errors.
129  *
130  * This function is intended mainly for development and
131  * should not normally be included in a production program.
132  */
133 void checkOpenGLStatus();
134 
135 // End of error messages
136 //@}
137 
138 
139 
140 // Forward declarations.
141 class Line;
142 class Plane;
143 class Vector;
144 class Quaternion;
145 
146 
147 
148 /**
149  * An instance is a point represented by four homogeneous coordinates.
150  * A point is represented by \a (x,y,z,w) in which each component is a \c GLfloat.
151  * If \a w=0, the point is `at infinity'. Points at infinity may be used like other
152  * points, but a few operations do not work for them. CUGL functions do not issue an
153  * error message when this happens: they simply return a default result.
154  *
155  * A Point is in normal form if \a w=1. A Point may be normalized if \a w!=0.
156  */
157 class Point
158 {
159 public:
160  friend class Line;
161  friend class Vector;
162  friend class Matrix;
163  friend class Plane;
164 
165  /**
166  * Construct a point with coordinates (x, y, z, w).
167  * Default parameter values: (0,0,0,1).
168  */
169  Point(GLfloat x = 0, GLfloat y = 0, GLfloat z = 0, GLfloat w = 1);
170 
171  /**
172  * Construct a Point from coordinates.
173  * \param coordinates is an array containing at least four coordinates.
174  * \pre The array must have at least four components.
175  */
176  Point (GLfloat coordinates[]);
177 
178  /**
179  * Convert a Quaternion to a Point.
180  * \note This is a rather peculiar operation and should not normally be used.
181  * It is intended for experiments with non-linear transformations.
182  * \param q is a quaternion.
183  */
184  Point (const Quaternion & q);
185 
186  /**
187  * Access coordinates of a point.
188  * \param i is the index of the coordinate: p[0] = x, p[1] = y, p[2] = z, p[3] = w.
189  * \note Error BAD_INDEX reported if \c i is not one of {0,1,2, 3}.
190  */
191  GLfloat & operator[](int i);
192 
193  /**
194  * Access coordinates of a point.
195  * This form is used with \c const instances (\c p[i] cannot appear on the left of \c =).
196  * \param i is the index of the coordinate: p[0] = x, p[1] = y, p[2] = z, p[3] = w.
197  * \note Error BAD_INDEX reported if \c i is not one of {0,1,2, 3}.
198  */
199  const GLfloat & operator[](int i) const;
200 
201  /**
202  * Normalize a point.
203  * A Point \a (x,y,z,w) is in normal form if \a w=1.
204  * \note Error ZERO_DIVISOR reported if \a w=0.
205  * \note The value of this Point is changed by this function.
206  */
207  void normalize();
208 
209  /**
210  * Return the normalized form of a Point.
211  * A Point \a (x,y,z,w) is in normal form if \a w=1.
212  * \note Error ZERO_DIVISOR reported if \a w=0.
213  */
214  Point unit() const;
215 
216  /**
217  * Draw the point using \c glVertex4f().
218  */
219  void draw() const;
220 
221  /**
222  * Use this point as a light position.
223  * If w = 0, the light is directional, otherwise it is positional.
224  * \param lightNum specifies which light to use: \a GL_LIGHT0, \a GL_LIGHT1, ...
225  */
226  void light(GLenum lightNum) const;
227 
228  /**
229  * Translate to the point using \c glTranslatef().
230  * \note If the point is at infinity (w = 0), this function has no effect.
231  */
232  void translate() const;
233 
234  /**
235  * Scale a Point.
236  * Scale the coordinates of a Point by dividing by the scalar \a s.
237  * This is implemented by multiplying the \a w component of the Point
238  * by \a s. If \a s=0, the result is a Point at infinity.
239  * \return the Point at \a (x,y,z,s*w).
240  */
241  Point operator/(GLfloat s) const;
242 
243  /**
244  * Displace a Point with a Vector.
245  * The components of the Vector are added to the corresponding components of the Point.
246  * If the Point is not in normal form, the Vector is implicitly scaled.
247  * \return Point at (x-w*v.x, y-w*v.y, z-w*v.z, w).
248  */
249  Point operator+=(const Vector & v);
250 
251  /**
252  * Displace a Point with a Vector
253  * The components of the Vector are subtracted from the corresponding components of the Point.
254  * If the Point is not in normal form, the Vector is implicitly scaled.
255  * \return Point at (x+w*v.x, y+w*v.y, z+w*v.z, w).
256  */
257  Point operator-=(const Vector & v);
258 
259  /**
260  * Displace a Point with a Vector.
261  * The components of the Vector are added to the corresponding components of the Point.
262  * If the Point is not in normal form, the Vector is implicitly scaled.
263  * \return Point at (p.x+p.w*v.x, p.y+p.w*v.y, p.z+p.w*v.z, p.w).
264  */
265  friend Point operator+(const Vector & v, const Point & p);
266 
267  /**
268  * Displace a Point with a Vector.
269  * The components of the Vector are added to the corresponding components of the Point.
270  * If the Point is not in normal form, the Vector is implicitly scaled.
271  * \return Point at (p.x+p.w*v.x, p.y+p.w*v.y, p.z+p.w*v.z, p.w).
272  */
273  friend Point operator+(const Point & p, const Vector & v);
274 
275  /**
276  * Scale a point.
277  * \return Point at (p.x + p.w*v.x, p.y + p.w*v.y, p.z + p.w*v.z).
278  */
279  friend Point operator*(const Point & p, GLfloat s);
280 
281  /**
282  * Scale a point.
283  * Multiply each of the components of the Point by s.
284  * In homogeneous coordinates, this operation does not change the ``position'' of the Point.
285  * However, it may be used, for example, to normalize a Point.
286  * \return The scaled Point.
287  */
288  friend Point operator*(GLfloat s, const Point & p);
289 
290  /**
291  * Return the vector corresponding to the displacement between the two points.
292  * 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).
293  * If \c p or \c q is a point at infinity, return the zero vector.
294  * \return the Vector corresponding to the displacement between the two points.
295  */
296  friend Vector operator-(const Point & p, const Point & q);
297 
298  /**
299  * Find the point where this line meets the plane p.
300  * Sets error BAD_LINE if the line lies within the plane.
301  * \return the Point at which Line \c k meets Plane \c p.
302  */
303  friend Point meet(const Line & k, const Plane & p);
304 
305  /**
306  * Compare two points.
307  * This function returns \c true only if corresponding components are exactly equal.
308  * Values that are theoretically equal but computed in different ways are likely
309  * to be unequal according to this function.
310  */
311  friend bool operator==(const Point & p, const Point & q);
312 
313  /**
314  * Compare two points.
315  * This function returns \c false only if corresponding components are exactly equal.
316  * Values that are theoretically equal but computed in different ways are likely
317  * to be unequal according to this function.
318  */
319  friend bool operator!=(const Point & p, const Point & q);
320 
321  /**
322  * Write "(x,y,z,w)" to output stream.
323  * Inserts the coordinates of the point into the output stream \c os
324  * in the format "(x,y,z,w)". The current settings of the stream formatting
325  * parameters are used. If a width is specified with \c setw(), it is applied
326  * to each coordinate, not to the point as a whole.
327  */
328  friend std::ostream & operator<<(std::ostream & os, const Point & p);
329 
330  /**
331  * Return the distance between a Point and a Plane.
332  * The result has the correct magnitude only if the Point and the Plane
333  * are both in normal form. In particular, the result is incorrect if
334  * the Point is at infinity. However, the sign of the result is correct
335  * in all cases, and so it is not necessary to provide normalized
336  * arguments if only the sign is important.
337  */
338  friend GLfloat dist(const Point & p, const Plane & s);
339 
340  /**
341  * Return the distance between a Point and a Plane.
342  * The result has the correct magnitude only if the Point and the Plane
343  * are both in normal form. In particular, the result is incorrect if
344  * the Point is at infinity. However, the sign of the result is correct
345  * in all cases, and so it is not necessary to provide normalized
346  * arguments if only the sign is important.
347  */
348  friend GLfloat dist(const Plane & s, const Point & p);
349 
350  /**
351  * Return the disgtance bewteen two points.
352  * \note Does not check that the points are normalized.
353  */
354  friend double dist(const Point & p, const Point & q)
355  {
356  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));
357  }
358 
359 private:
360 
361  /** X coordinate of point. */
362  GLfloat x;
363 
364  /** Y coordinate of point. */
365  GLfloat y;
366 
367  /** Z coordinate of point. */
368  GLfloat z;
369 
370  /** W coordinate of point. */
371  GLfloat w;
372 
373 };
374 
375 
376 /**
377  * An instance is a line defined by two Points.
378  * Lines are occasionally useful. For example, it is simple to
379  * display surface normals using this class.
380  * A Line is represented by the two Points which are its end-points.
381  */
382 
383 class Line
384 {
385 public:
386 
387  friend class Plane;
388 
389  /**
390  * Construct the Line from Point \c p to Point \c q.
391  */
392  Line(const Point & p, const Point & q);
393 
394  /**
395  * Construct the Line from Point \c p to Point \c p+v.
396  */
397  Line(const Point & p, const Vector & v);
398 
399  /**
400  * Find the point where this line meets the plane p.
401  */
402  friend Point meet(const Line & k, const Plane & p);
403 
404  /**
405  * Draw the line using \c glBegin(GL_LINE) ....
406  */
407  void draw() const;
408 
409  /**
410  * Compare two lines.
411  * This function returns \c true only if corresponding components are exactly equal.
412  * Values that are theoretically equal but computed in different ways are likely
413  * to be unequal according to this function.
414  */
415  friend bool operator==(const Line & x, const Line & y);
416 
417  /**
418  * Compare two lines.
419  * This function returns \c false only if corresponding components are exactly equal.
420  * Values that are theoretically equal but computed in different ways are likely
421  * to be unequal according to this function.
422  */
423  friend bool operator!=(const Line & x, const Line & y);
424 
425  /**
426  * Write a representation of the line to the output stream.
427  * The format is \a pt->pt where "\a pt" is the format used for points.
428  * If \c setw is used to set the width, it is passed to the inserter
429  * for Point.
430  */
431  friend std::ostream & operator<<(std::ostream & os, const Line & k);
432 
433 private:
434  /** Start point of line. */
436 
437  /** Finish point of line. */
438  Point f; // finish point
439 };
440 
441 
442 /**
443  * An instance is a plane defined by its equation \a Ax+By+Cz+D=0.
444  *
445  * Planes are used for clipping, shadows, and reflections
446  * (see class Matrix).
447  *
448  * Homogeneous points (x,y,z,w) lie on the plane if Ax+By+Cz+Dw=0.
449  * The notation for a plane is \a <A,B,C,D>. The plane \a <0,0,0,D> is undefined.
450  * An attempt to construct such a plane sets the error flag to BAD_PLANE and the
451  * plane is set to <0,1,0,0> (in the conventional OpenGL frame, this often corresponds
452  * to the ground, \a y=0).
453  *
454  * A Plane is in normal form if the Vector \a (A,B,C) is a unit vector.
455  * A Plane can be normalized by scaling \a A,B,C,D.
456  */
457 
458 class Plane
459 {
460  friend class Matrix;
461 
462 public:
463  /**
464  * Construct a plane given the coefficients of its equation \a Ax+By+Cx+D=0.
465  * If no arguments are provided, construct the plane y = 0.
466  */
467  Plane(GLfloat a = 0, GLfloat b = 1, GLfloat c = 0, GLfloat d = 0);
468 
469  /**
470  * Construct a plane containing the three given points.
471  */
472  Plane(const Point & p, const Point & q, const Point & r);
473 
474  /**
475  * Construct a plane containing the line \c s and the point \c p.
476  */
477  Plane(const Line & s, const Point & p);
478 
479  /**
480  * Construct the plane orthogonal to \c v and passing through \c p.
481  */
482  Plane(const Vector & v, const Point & p);
483 
484  /**
485  * Normalize this plane.
486  * The Plane \a (A,B,C,D) is in normal form when \a (A,B,C) is a unit vector.
487  * Error ZERO_DIVISOR reported if \a |(A,B,C|=0 (which should not be the case for a well-formed plane).
488  * \note The value of the Plane is changed by this function.
489  */
490  void normalize();
491 
492  /**
493  * Return a normalized Plane equivalent to this plane.
494  * The Plane \a (A,B,C,D) is in normal form when \a (A,B,C) is a unit vector.
495  * Error ZERO_DIVISOR reported if \a |(A,B,C|=0 (which should not be the case for a well-formed plane).
496  */
497  Plane unit() const;
498 
499  /**
500  * Return a vector of unit length that is normal to the plane.
501  */
502  Vector normal() const;
503 
504  /**
505  * Use this plane as a clipping plane.
506  * This function calls \c glClipPlane
507  * to suppress rendering of objects on one side of the plane.
508  * \param index must be one of GL_CLIP_PLANE0, GL_CLIP_PLANE1, ... A
509  * An implementation of OpenGL is supposed to provide at least six
510  * clipping planes, numbered 0,1,...,5.
511  */
512  void clipPlane(GLenum index) const;
513 
514  /**
515  * Find the point where this line meets the plane p.
516  */
517  friend Point meet(const Line & k, const Plane & p);
518 
519  /**
520  * Compare two planes.
521  * This function returns \c true only if corresponding components are exactly equal.
522  * Values that are theoretically equal but computed in different ways are likely
523  * to be unequal according to this function.
524  */
525  friend bool operator==(const Plane & x, const Plane & y);
526 
527  /**
528  * Compare two planes.
529  * This function returns \c false only if corresponding components are exactly equal.
530  * Values that are theoretically equal but computed in different ways are likely
531  * to be unequal according to this function.
532  */
533  friend bool operator!=(const Plane & x, const Plane & y);
534 
535  /**
536  * Write a description of the plane to the output stream as \a <a,b,c,d>.
537  * Inserts the components of the plane into the output
538  * stream \c os in the format \a <a,b,c,d>. The current settings
539  * of the stream formatting parameters are used. If a width
540  * is specified with \c setw(), it is applied to each component
541  * rather than to the plane as a whole.
542  */
543  friend std::ostream & operator<<(std::ostream & os, const Plane & p);
544 
545  /**
546  * Return the distance between a Point and a Plane.
547  * The result has the correct magnitude only if the Point and the Plane
548  * are both in normal form. In particular, the result is incorrect if
549  * the Point is at infinity. However, the sign of the result is correct
550  * in all cases, and so it is not necessary to provide normalized
551  * arguments if only the sign is important.
552  */
553  friend GLfloat dist(const Point & p, const Plane & s);
554 
555  /**
556  * Return the distance between a Point and a Plane.
557  * The result has the correct magnitude only if the Point and the Plane
558  * are both in normal form. In particular, the result is incorrect if
559  * the Point is at infinity. However, the sign of the result is correct
560  * in all cases, and so it is not necessary to provide normalized
561  * arguments if only the sign is important.
562  */
563  friend GLfloat dist(const Plane & s, const Point & p);
564 
565  /** Return the A component of the plane defined by Ax+By+Cz+d=0. */
566  GLfloat getA() { return a; }
567 
568  /** Return the B component of the plane defined by Ax+By+Cz+d=0. */
569  GLfloat getB() { return b; }
570 
571  /** Return the C component of the plane defined by Ax+By+Cz+d=0. */
572  GLfloat getC() { return c; }
573 
574  /** Return the D component of the plane defined by Ax+By+Cz+d=0. */
575  GLfloat getD() { return d; }
576 
577 
578 private:
579  /** Coefficient of \a x in the plane equation. */
580  GLfloat a;
581 
582  /** Coefficient of \a y in the plane equation. */
583  GLfloat b;
584 
585  /** Coefficient of \a z in the plane equation. */
586  GLfloat c;
587 
588  /** Coefficient of \a w in the plane equation. */
589  GLfloat d;
590 };
591 
592 class Matrix;
593 
594 /**
595  * An instance is a vector with 3 real components.
596  * A vector v is a 3-vector represented by three orthogonal components
597  * \a vx, \a vy, and \a vz. The norm of the vector \a v is vx*vx+vy*vy+vz*vz.
598  * The length of \c v is \c sqrt(norm(v)).
599  */
600 class Vector
601 {
602  friend class Point;
603  friend class Matrix;
604  friend class Quaternion;
605 
606 public:
607  /**
608  * Construct the zero vector: (0,0,0).
609  */
610  Vector() : x(0), y(0), z(0)
611  {}
612 
613  /**
614  * Construct the vector (x,y,z).
615  */
616  Vector(GLfloat x, GLfloat y, GLfloat z)
617  : x(x), y(y), z(z)
618  {}
619 
620  /**
621  * Construct a vector from the array \c coordinates.
622  * \pre The array must have at least three components.
623  */
624  Vector(GLfloat coordinates[]);
625 
626  /**
627  * Construct a vector normal to the polygon defined
628  * by the given points using Martin Newell's algorithm.
629  * The normal vector will be exact if the points lie in a plane,
630  * otherwise it will be a sort of average value. As with OpenGL,
631  * the vector will point in the direction from which the points
632  * are enumerated in a counter-clockwise direction.
633  *
634  * Unlike other functions, this function does \b not use homogeneous coordinates.
635  * The points are assumed to have (x,y,z) coordinates; the w component is ignored.
636  * \param points is an array of points.
637  * \param numPoints is the number of points in the array.
638  * \return the vector normal to the plane defined by \a points.
639  * \note The vector is \b not a unit vector because it will probably
640  * be averaged with other vectors.
641  */
642  Vector(Point points[], int numPoints);
643 
644  /**
645  * Construct a vector from two points.
646  * Vector(p, q) is equivalent to p - q.
647  */
648  Vector(const Point & p, const Point & q);
649 
650  /**
651  * Construct a vector from a quaternion by ignoring the scalar component of the quaternion.
652  * Vector(q) constructs the vector returned by \c q.vector().
653  * \param q is the \a Quaternion whose vector component is to be used.
654  */
655  explicit Vector(const Quaternion & q);
656 
657  /**
658  * Add vector \c v to this vector.
659  */
660  Vector operator+=(const Vector & v);
661 
662  /**
663  * Subtract vector \c v from this vector.
664  */
665  Vector operator-=(const Vector & v);
666 
667  /**
668  * Return Vector (-x,-y,-z).
669  */
670  Vector operator-() const;
671 
672  /**
673  * Multiply each component of the vector by \c scale.
674  */
675  Vector operator*=(GLfloat scale);
676 
677  /**
678  * Return the vector (x/scale,y/scale,z/scale).
679  * Error ZERO_DIVISOR reported if \c scale is zero.
680  * \return the Vector (x/scale,y/scale,z/scale).
681  */
682  Vector operator/(GLfloat scale) const;
683 
684  /**
685  * Divide each component of this vector by \c scale and return the new value.
686  * Error ZERO_DIVISOR reported if \c scale is zero.
687  */
688  Vector operator/=(GLfloat scale);
689 
690  /**
691  * Normalize this vector.
692  * See also \a Vector::unit().
693  * Reports error ZERO_NORM if the vector is zero.
694  * \note The value of this vector is changed by this operation.
695  */
696  void normalize();
697 
698  /**
699  * Return a unit vector with the same direction as this vector.
700  * See also \a Vector::normalize().
701  * Reports error ZERO_NORM if the vector is zero.
702  * \note The value of this vector is not changed by this operation.
703  */
704  Vector unit() const;
705 
706  /**
707  * Return the norm of this vector.
708  * The norm of a vector is the sum of its squared components
709  * and is also the square of the length.
710  * \return the norm of this vector.
711  */
712  GLfloat norm() const;
713 
714  /**
715  * Return the length of this vector.
716  * The length of a vector is the square root of its norm.
717  * \return the length of this vector.
718  */
719  GLfloat length() const;
720 
721  /**
722  * Use this vector to translate an object.
723  * This is implemented by passing the vector to \c glTranslate().
724  */
725  void translate() const;
726 
727  /**
728  * Use this vector as a normal vector when drawing a surface.
729  * This is implemented by passing the vector to \c glNormal().
730  */
731  void drawNormal() const;
732 
733  /**
734  * Construct the skew-symmetric matrix corresponding to this vector.
735  */
736  Matrix skew();
737 
738  /**
739  * Draw this vector as a line in the graphics window.
740  * The line joins \a P and \a P+V, where \a P is the point provided,
741  * or the origin if no point is given.
742  * \param p is the start point for the vector.
743  */
744  void draw(const Point & p = Point()) const;
745 
746  /**
747  * Get or set a reference to a component of this vector.
748  * \c v[0] is the \a x component; \c v[1] is the \a y component; \c v[2] is the \a z component.
749  * Error BAD_INDEX reported if \c i is not one of 0, 1, 2.
750  */
751  GLfloat & operator[](int i);
752 
753  /**
754  * Get a reference to a component of this vector.
755  * This form is used for \c const instances (\c v[i] cannot appear on the left of \c =).
756  * \c v[0] is the \a x component; \c v[1] is the \a y component; \c v[2] is the \a z component.
757  * Error BAD_INDEX reported if \c i is not one of 0, 1, 2.
758  */
759  const GLfloat & operator[](int i) const;
760 
761  /**
762  * Return cross product of vectors \c u and \c v.
763  */
764  friend Vector cross(const Vector & u, const Vector & v);
765 
766  /**
767  * Return cross product of vectors \c u and \c v.
768  */
769  friend Vector operator*(const Vector & u, const Vector & v);
770 
771  /**
772  * Return dot product of vectors \c u and \c v.
773  */
774  friend GLfloat dot(const Vector & u, const Vector & v);
775 
776  /**
777  * Return Vector \a s*v.
778  */
779  friend Vector operator*(const Vector & v, GLfloat s);
780 
781  /**
782  * Return Vector \a s*v.
783  */
784  friend Vector operator*(GLfloat s, const Vector & v);
785 
786  /**
787  * Return Vector \a u+v.
788  */
789  friend Vector operator+(const Vector & u, const Vector & v);
790 
791  /**
792  * Return Vector \a u-v.
793  */
794  friend Vector operator-(const Vector & u, const Vector & v);
795 
796  /**
797  * Displace a Point with a Vector.
798  * \return Point at (p.x+p.w*v.x, p.y+p.w*v.y, p.z+p.w*v.z, p.w).
799  */
800  friend Point operator+(const Vector & v, const Point & p);
801 
802  /**
803  * Return Point \c p displaced by vector \c v.
804  */
805  friend Point operator+(const Point & p, const Vector & v);
806 
807  /**
808  * Compare two vectors.
809  * This function returns \c true only if corresponding components are exactly equal.
810  * Values that are theoretically equal but computed in different ways are likely
811  * to be unequal according to this function.
812  */
813  friend bool operator==(const Vector & x, const Vector & y);
814 
815  /**
816  * Compare two vectors.
817  * This function returns \c false only if corresponding components are exactly equal.
818  * Values that are theoretically equal but computed in different ways are likely
819  * to be unequal according to this function.
820  */
821  friend bool operator!=(const Vector & x, const Vector & y);
822 
823  /**
824  * Write vector to output stream as \a (x,y,z).
825  * Inserts the components of the vector into the output
826  * stream \c os in the format \a (x,y,z). The current settings
827  * of the stream formatting parameters are used. If a width
828  * is specified with \c setw(), it is applied to each coordinate,
829  * not to the vector as a whole.
830  */
831  friend std::ostream & operator<<(std::ostream & os, const Vector & v);
832 
833 private:
834 
835  /** X component of vector. */
836  GLfloat x;
837 
838  /** Y component of vector. */
839  GLfloat y;
840 
841  /** Z component of vector. */
842  GLfloat z;
843 };
844 
845 /**
846  * Unit vector parallel to \a X axis.
847  */
848 const Vector I(1, 0, 0);
849 
850 /**
851  * Unit vector parallel to \a Y axis.
852  */
853 const Vector J(0, 1, 0);
854 
855 
856 /**
857  * Unit vector parallel to \a Z axis.
858  */
859 const Vector K(0, 0, 1);
860 
861 /**
862  * An instance is a matrix compatible with an OpenGL transformation matrix.
863  * An instance of class Matrix is a 4 by 4 matrix with
864  * components of type \c GLfloat. The components are ordered
865  * in the same way as an OpenGL matrix (column-row order,
866  * for compatibility with FORTRAN).
867 
868  * Note that OpenGL performs matrix calculations very efficiently.
869  * As far as possible, construct transformations using sequences of
870  * OpenGL matrix operations. Construct and use the matrices here
871  * only if OpenGL does not provide the required facilities.
872  */
873 class Matrix
874 {
875 public:
876 
877  /**
878  * Construct the identity matrix.
879  */
880  Matrix();
881 
882  /**
883  * Construct a copy of an arbitrary OpenGL matrix.
884  */
885  Matrix(GL_Matrix r);
886 
887  /**
888  * Construct a copy of an OpenGL projection or model view matrix.
889  \param mode should be \c GL_PROJECTION_MATRIX or \c GL_MODELVIEW_MATRIX.
890 
891  Report error BAD_MATRIX_MODE and construct identity matrix
892  for other values of mode.
893  */
894  explicit Matrix(GLenum mode);
895 
896  /**
897  * Construct a rotation matrix.
898  \param axis is the axis of rotation.
899  \param theta is the magnitude of the rotation.
900  \note The angle \c theta should be in radians (unlike OpenGL, which uses degrees).
901  */
902  Matrix(const Vector & axis, double theta);
903 
904  /**
905  * Construct a matrix that reflects a point in the given plane.
906  * The matrix can be used to simulate a mirror in an OpenGL program.
907  * See also Matrix::reflect().
908  \param refl is the plane of reflection.
909  */
910  explicit Matrix(const Plane & refl);
911 
912  /**
913  * Construct a shadow matrix from a point light source and a plane.
914  * The matrix transforms an object into its shadow on the given plane.
915  * It is your job to ensure that the shadow has the appropriate colour, transparency, etc.
916  * The light source may be a local point (w > 0) or a point at infinity (w = 0).
917  * See also \c Matrix::shadow().
918  \param lightPos is the position of the light source.
919  \param plane is the plane onto which the shadow is projected.
920 
921  */
922  Matrix(const Point & lightPos, const Plane & plane);
923 
924  /**
925  * Construct a rotation matrix from a quaternion.
926  * \pre The quaternion must be a unit quaternion.
927  */
928  explicit Matrix(const Quaternion & q);
929 
930  /**
931  * Construct the matrix that rotates one vector to another.
932  * \param u is a vector representing an initial orientation.
933  * \param v is a vector representing the final orientation.
934  * The matrix, applied to \a u, will yield \a v.
935  * \pre The vectors \a u and \a v must be unit vectors.
936  */
937  Matrix(const Vector & u, const Vector & v);
938 
939  /**
940  * Construct a matrix from 16 floats.
941  */
942  Matrix(
943  const GLfloat m00, const GLfloat m10, const GLfloat m20, const GLfloat m30,
944  const GLfloat m01, const GLfloat m11, const GLfloat m21, const GLfloat m31,
945  const GLfloat m02, const GLfloat m12, const GLfloat m22, const GLfloat m32,
946  const GLfloat m03, const GLfloat m13, const GLfloat m23, const GLfloat m33 );
947 
948  /**
949  * Return the quaternion corresponding to this matrix.
950  * This function may report BAD_ROTATION_MATRIX.
951  * \note The result may be imprecise if the rotation angle is close to 180 degrees.
952  * \pre The matrix must be a rotation matrix.
953  */
954  Quaternion quaternion() const;
955 
956  /**
957  * Return a pointer to the first element of the matrix.
958  * This function may be used in conjunction with
959  * \c glMultMatrix() to apply this matrix to the current OpenGL matrix.
960  * \return a pointer to the first element of the matrix.
961  */
962  GLfloat *get()
963  ;
964 
965  /**
966  * Return the transpose of this matrix.
967  */
968  Matrix transpose() const;
969 
970  /**
971  * Return the trace of this matrix.
972  * The trace will include the bottom right element, m[3][3].
973  */
974  GLfloat trace()
975  {
976  return m[0][0] + m[1][1] + m[2][2] + m[3][3];
977  }
978 
979  /**
980  * Compute the inverse of this matrix using Gauss-Jordan elimination.
981  * If the matrix is singular, report \c SINGULAR_MATRIX and return the zero matrix.
982  * Calculations are performed in double precision because this gives
983  * slightly better results.
984  * The prefix operator ~ has the same effect.
985  * \return the inverse of this matrix.
986  */
987  Matrix inv() const;
988 
989  /**
990  * Return the inverse of this matrix.
991  * This provides an alternative syntax for inv().
992  * \return the inverse of this matrix.
993  */
994  Matrix operator~() const;
995 
996  /**
997  * Multiply the current OpenGL matrix by this matrix.
998  */
999  void apply() const;
1000 
1001  /**
1002  * Apply this matrix to a point.
1003  */
1004  Point apply(const Point & p) const;
1005 
1006  /**
1007  * Apply this matrix to a vector.
1008  */
1009  Vector apply(const Vector & v) const;
1010 
1011  /**
1012  * Return the axis of a rotation matrix.
1013  * Report error \c BAD_ROTATION_MATRIX and leave result undefined,
1014  * if the matrix is not a rotation.
1015  * \return the axis of a rotation matrix.
1016  */
1017  Vector axis() const;
1018 
1019  /**
1020  * Return the angle (in radians) of a rotation matrix.
1021  * Report error \c BAD_ROTATION_MATRIX and leave result undefined,
1022  * if the matrix is not a rotation.
1023  * \return the angle (in radians) of a rotation matrix.
1024  */
1025  double angle() const;
1026 
1027  /**
1028  * Return a reference to the element \c m[i][j] of the matrix.
1029  * \pre The values of \c i and \c j must be in the range [0,3].
1030  * \return the element \c m[i][j] of the matrix.
1031  */
1032  GLfloat & operator()(int i, int j);
1033 
1034  /**
1035  * Return a reference to the element \c m[i][j] of the \c const matrix.
1036  * This version is used for \c const instances (\c m(i,j) cannot appear on the left of \c =).
1037  * \pre The values of \c i and \c j must be in the range [0,3].
1038  * \return the element \c m[i][j] of the matrix.
1039  */
1040  const GLfloat & operator()(int i, int j) const;
1041 
1042  /**
1043  * Set the matrix so that it reflects a point in the plane \c p.
1044  * The matrix can be used to simulate a mirror in an OpenGL program.
1045  * See also constructors for class Matrix.
1046  \param p is the plane of reflection.
1047  */
1048  void reflect(const Plane & p);
1049 
1050  /**
1051  * Set the matrix so that it creates a shadow on the plane \c p from a light source \c lightPos.
1052  * The matrix transforms an object into its shadow on the given plane.
1053  * It is your job to ensure that the shadow has the appropriate colour, transparency, etc.
1054  * The point \c p may be either a local point (w > 0) or a point at infinity (w = 0).
1055  * See also constructors for class Matrix.
1056  \param lightPos is the position of the light source causing the shadow.
1057  \param plane is the plane upon which the shadow is cast.
1058  */
1059  void shadow(const Point & lightPos, const Plane & plane);
1060 
1061  /** Add and assign matrices. */
1062  Matrix operator+=(const Matrix & rhs);
1063 
1064  /** Add two matrices. */
1065  friend Matrix operator+(const Matrix & m, const Matrix & n);
1066 
1067  /** Subtract and assign matrices. */
1068  Matrix operator-=(const Matrix & rhs);
1069 
1070  /** Subtract two matrices. */
1071  friend Matrix operator-(const Matrix & m, const Matrix & n);
1072 
1073  /** Multiply and assign matrices. */
1074  Matrix operator*=(const Matrix & rhs);
1075 
1076  /** Multiply two matrices. */
1077  friend Matrix operator*(const Matrix & m, const Matrix & n);
1078 
1079  /** Multiply scalar and matrix. */
1080  friend Matrix operator*(GLfloat s, const Matrix & m);
1081 
1082  /** Multiply matrix and scalar. */
1083  friend Matrix operator*(const Matrix & m, GLfloat s);
1084 
1085  /** Multiply by scalar and assign. */
1086  Matrix & operator*=(GLfloat s);
1087 
1088  /** Divide by scalar and assign. */
1089  Matrix & operator/=(GLfloat s);
1090 
1091  /** Divide by scalar. */
1092  friend Matrix operator/(const Matrix & m, GLfloat s);
1093 
1094  /**
1095  * Compare two matrices.
1096  * This function returns \c true only if corresponding components are exactly equal.
1097  * Values that are theoretically equal but computed in different ways are likely
1098  * to be unequal according to this function.
1099  */
1100  friend bool operator==(const Matrix & x, const Matrix & y);
1101 
1102  /**
1103  * Compare two matrices.
1104  * This function returns \c false only if corresponding components are exactly equal.
1105  * Values that are theoretically equal but computed in different ways are likely
1106  * to be unequal according to this function.
1107  */
1108  friend bool operator!=(const Matrix & x, const Matrix & y);
1109 
1110  /**
1111  * Write a four-line image of the matrix to the output stream.
1112  * The current settings of the stream formatting parameters are used.
1113  * If a width is specified with \c setw(), it is applied to each
1114  * element of the matrix, not the matrix as a whole.
1115  */
1116  friend std::ostream & operator<<(std::ostream & os, const Matrix & m);
1117 
1118 private:
1119 
1120  /** The elements of the matrix. */
1122 };
1123 
1124 
1125 
1126 /**
1127  * An instance is a quaternion represented as a (scalar, vector) pair.
1128  * We use the notation \a (s,v) for a quaternion with scalar component
1129  * \a s and vector component \a v. Although arbitrary quaternions can be
1130  * constructed, all of the applications of quaternions provided by
1131  * the class assume that the quaternion is a unit quaternion
1132  * representing a rotation.
1133  */
1135 {
1136 public:
1137 
1138  friend class Vector;
1139  friend class Matrix;
1140 
1141  /**
1142  * Construct the quaternion (1,(0,0,0)) (the null rotation).
1143  */
1144  Quaternion() : s(1)
1145  {}
1146 
1147  /**
1148  * Construct the quaternion (s, (x,y,z)).
1149  */
1150  Quaternion(GLfloat s, GLfloat x, GLfloat y, GLfloat z)
1151  : s(s), v(Vector(x,y,z))
1152  {}
1153 
1154  /**
1155  * Construct the quaternion \a (0,v).
1156  * The result will be a unit quaternion if \a v is a unit vector,
1157  * in which case the quaternion represents a rotation through
1158  * 90 degrees about the axis \a v.
1159  */
1160  Quaternion(const Vector & v) : s(0), v(v)
1161  {}
1162 
1163  /**
1164  * Construct the quaternion \a (s,v).
1165  * \note Don't confuse this constructor with Quaternion(axis,angle).
1166  * \param s is the scalar component of the quaternion.
1167  * \param v is the vector component of the quaternion.
1168  */
1169  Quaternion(GLfloat s, const Vector & v) : s(s), v(v)
1170  {}
1171 
1172  /**
1173  * Construct a quaternion with the given axis of rotation and angle.
1174  * \note Don't confuse this constructor with Quaternion(s,v).
1175  * \pre The axis must be a unit vector.
1176  * \param axis gives the axis of rotation.
1177  * \param angle gives the amount of the rotation.
1178  */
1180  : s(GLfloat(cos(angle/2))), v(GLfloat(sin(angle/2)) * axis)
1181  {}
1182 
1183  /**
1184  * Construct the quaternion corresponding to an OpenGL rotation matrix.
1185  * The result may be imprecise if the rotation angle is close to 180 degrees.
1186  * This function may report BAD_ROTATION_MATRIX.
1187  * \pre The matrix must be a rotation matrix.
1188  */
1189  Quaternion(Matrix m);
1190 
1191  /**
1192  * Construct a quaternion from Euler angles.
1193  */
1194  Quaternion(double xr, double yr, double zr);
1195 
1196  /**
1197  * Construct a Quaternion from a Point.
1198  * The quaternion consists of the vector \a (p[0],p[1],p[2]) and the scalar \a p[3].
1199  * \note This is a unusual operation and should not normally be used.
1200  * It is intended for experiments with non-linear transformations.
1201  */
1202  Quaternion(const Point & p);
1203 
1204  /**
1205  * Construct the quaternion that rotates one vector to another.
1206  * \param u is a vector representing an initial orientation.
1207  * \param v is a vector representing the final orientation.
1208  * The quaternion, applied to \a u, will yield \a v.
1209  * \pre The vectors \a u and \a v must be unit vectors.
1210  */
1211  Quaternion(const Vector & u, const Vector & v);
1212 
1213  /**
1214  * Add the quaternion q to this quaternion.
1215  */
1216  Quaternion operator+=(const Quaternion & q);
1217 
1218  /**
1219  * Subtract the quaternion q from this quaternion.
1220  */
1221  Quaternion operator-=(const Quaternion & q);
1222 
1223  /**
1224  * Return the quaternion \a q+r.
1225  * \note The sum of two unit quaternions is not in general a unit quaternion.
1226  * However, it occasionally appears in expressions such as k q1 + (1 - k) q2,
1227  * which does yield a unit quaternion.
1228  * \return the Quaternion \a q+r.
1229  */
1230  friend Quaternion operator+(const Quaternion & q, const Quaternion & r);
1231 
1232  /**
1233  * Return the quaternion \a q-r.
1234  * \note The difference of two unit quaternions is not in general a unit quaternion.
1235  * \return the Quaternion \a q-r.
1236  */
1237  friend Quaternion operator-(const Quaternion & q, const Quaternion & r);
1238 
1239  /**
1240  * Return the quaternion product \a q*r.
1241  * If \c q and \c r represent
1242  * rotations, then \a q*r represents the rotation \a q followed by the rotation \a r.
1243  * \note Quaternion multiplication is not commutative: \a q*r is not equal to \a r*q.
1244  * \return the Quaternion product \a q*r.
1245  */
1246  friend Quaternion operator*(const Quaternion & q, const Quaternion & r);
1247 
1248  /**
1249  * Promote the vector \a v to a quaternion \a qv and
1250  * return the quaternion product \a qv*q.
1251  */
1252  friend Quaternion operator*(const Vector & v, const Quaternion & q);
1253 
1254  /**
1255  * Promote the vector \a v to a quaternion \a qv and
1256  * return the quaternion product \a q*qv.
1257  */
1258  friend Quaternion operator*(const Quaternion & q, const Vector & v);
1259 
1260  /** REMOVED: ambiguous operattion - need left and right quotients.
1261  * Return the quaternion ratio \a q/r.
1262  * If q and r represent
1263  * rotations, then \a q/r represents the rotation \a q followed by
1264  * the rotation that is the inverse of \a r.
1265  * \return the Quaternion ratio \a q/r.
1266  */
1267  // friend Quaternion operator/(const Quaternion & q, const Quaternion & r);
1268 
1269  /**
1270  * Multiply this quaternion by \c q and return the result.
1271  */
1272  Quaternion & operator*=(const Quaternion & q);
1273 
1274  /**
1275  * Divide this quaternion by \c q and return the result.
1276  */
1277  Quaternion & operator/=(const Quaternion & q);
1278 
1279  /**
1280  * Return the quaternion \a a*q, where \a a is a scalar.
1281  * \a a is a scalar and a*(s,v) = (a*s, a*v).
1282  * \return the Quaternion \a a*q.
1283  */
1284  friend Quaternion operator*(const Quaternion & q, GLfloat a);
1285 
1286  /**
1287  * Multiply by scalar and assign.
1288  */
1289  Quaternion & operator*=(GLfloat s);
1290 
1291  /**
1292  * Divide by scalar and assign.
1293  */
1294  Quaternion & operator/=(GLfloat s);
1295 
1296  /**
1297  * Return the quaternion \a a*q, where \a a is a scalar.
1298  * \a a is a scalar and a*(s,v) = (a*s, a*v).
1299  * \return the Quaternion \a a*q.
1300  */
1301  friend Quaternion operator*(GLfloat a, const Quaternion & q);
1302 
1303  /**
1304  * Return the quaternion \a q/a, where \a a is a scalar.
1305  * \a a is a scalar and (s,v)/a = (s/a, v/a).
1306  * Report error ZERO_DIVISOR if \a a = 0.
1307  * \return the Quaternion \a q/a.
1308  */
1309  Quaternion operator/(GLfloat scale) const;
1310 
1311  /**
1312  * Normalize this quaternion.
1313  * See also Quaternion::unit().
1314  * Report error ZERO_DIVISOR if q = (0,(0,0,0)).
1315  * \note The value of this quaternion is changed by this operation.
1316  */
1317  void normalize();
1318 
1319  /**
1320  * Return a unit quaternion corresponding to this quaternion.
1321  * See also Quaternion::normalize().
1322  * Report error ZERO_DIVISOR if q = (0,(0,0,0)).
1323  * \note The value of this quaternion is not changed by this operation.
1324  */
1325  Quaternion unit() const;
1326 
1327  /**
1328  * Return the conjugate of this quaternion.
1329  * The conjugate of (s,v) is (s,-v).
1330  * The inverse and conjugate of a unit quaternion are equal.
1331  * \return the conjugate of this quaternion.
1332  */
1333  Quaternion conj() const;
1334 
1335  /**
1336  * Return Inverse of this quaternion.
1337  * q.inv() = q.conj()/q.norm().
1338  * The inverse and conjugate of a unit quaternion are equal.
1339  * Report error ZERO_DIVISOR if q.norm() = 0.
1340  * If \c q represents a rotation then \c q.inv() represents
1341  * the opposite, or inverse, rotation.
1342  * The prefix operator ~ has the same effect.
1343  * \return the inverse of this quaternion.
1344  */
1345  Quaternion inv() const;
1346 
1347  /**
1348  * Return Inverse of this quaternion.
1349  * This provides alternative syntax for \c inv().
1350  * \return the inverse of this quaternion.
1351  */
1352  Quaternion operator~() const;
1353 
1354  /**
1355  * Apply this quaternion to the vector \c w.
1356  * The vector \c w is not changed.
1357  * \return the rotated vector \c q.inv()*w*q.
1358  */
1359  Vector apply(const Vector & w) const;
1360 
1361  /**
1362  * Return Vector component \a v of the quaternion \a q = \a (s,v).
1363  * The same effect can be achieved with the constructor \c Vector::Vector(q).
1364  */
1365  Vector vector() const;
1366 
1367  /**
1368  * Return Scalar component \a s of the quaternion \a q = \a (s,v).
1369  */
1370  GLfloat scalar() const;
1371 
1372  /**
1373  * Return the norm of this quaternion.
1374  * The norm is the sum of the squared components
1375  * and is also the square of the magnitude.
1376  * \return the norm of this quaternion.
1377  */
1378  GLfloat norm() const;
1379 
1380  /**
1381  * Return the magnitude of this quaternion.
1382  * The magnitude is the square root of the norm.
1383  * \return the magnitude of this quaternion.
1384  */
1385  GLfloat magnitude() const;
1386 
1387  /**
1388  * Compute the rotation matrix corresponding to this quaternion
1389  * and store it in the Matrix \c m.
1390  */
1391  void matrix(Matrix & m) const;
1392 
1393  /**
1394  * Compute the rotation matrix corresponding to this quaternion
1395  * and store it in the OpenGL matrix \c m.
1396  */
1397  void matrix(GL_Matrix m) const;
1398 
1399  /**
1400  * Apply the current quaternion to the current OpenGL matrix.
1401  */
1402  void apply() const;
1403 
1404  /**
1405  * Return the axis of rotation of this quaternion.
1406  * \pre The quaternon must be a unit quaternion.
1407  * \return a unit vector giving the axis of rotation of the quaternion.
1408  */
1409  Vector axis() const;
1410 
1411  /**
1412  * Return the amount of rotation of this quaternion.
1413  * \pre The quaternon must be a unit quaternion.
1414  * \return the amount of rotation provided by this quaternion in radians.
1415  */
1416  double angle() const;
1417 
1418  /**
1419  * Integrate an angular velocity vector.
1420  * The rotation represented by this quaternion will be updated by
1421  * applying the angular velocity \c omega for a short interval of
1422  * time \c dt.
1423  * \param omega is an angular velocity vector.
1424  * \param dt is the time increment for integration.
1425  */
1426  void integrate(const Vector & omega, double dt);
1427 
1428  /**
1429  * Return Euler angles for this quaternion.
1430  * The quaternion gives the rotation that would be obtained by calling
1431  * \c glRotatef three times, with arguments (\c xr,1,0,0), (\c yr,0,1,0), and
1432  * (\c zr,0,0,1).
1433  * \pre The angle transformations are applied in \a x, \a y, \a z order.
1434  * \return the Euler angles corresponding to this quaternion.
1435  */
1436  void euler(double & xr, double & yr, double & zr) const;
1437 
1438  /**
1439  * Use this quaternion to simulate a trackball.
1440  * To use this function in an OpenGL program, use the default constructor
1441  * to construct the quaternion \a q = (1,(0,0,0)). In the display function,
1442  * use \c q.rotate() to modify the OpenGL model view matrix.
1443  *
1444  * Call \c trackball(x1,y1,x2,y2) to record a small mouse movement
1445  * from \a (x1,y1) to \a (x2,y2). The coordinates should be normalized
1446  * so that both \a x and \a y are in [-1,1].
1447  *
1448  * This function will compute a rotation will apply this rotation to
1449  * the current quaternion. The rotation simulates a trackball.
1450  */
1451  void trackball(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
1452 
1453  /**
1454  * log(q) of a quaternion is a pure quaternion (scalar part 0).
1455  * log(q) is an element of the Lie algebra of the quaternion group.
1456  * log(1;0) = (0;0).
1457  */
1458  friend Quaternion log(const Quaternion & q)
1459  {
1460  return (q.s == 1) ?
1461  Quaternion(0.0, Vector()) :
1462  Quaternion(0.0, (acos(q.s) / sqrt(1 - q. s * q.s))* q.v);
1463  }
1464 
1465  /**
1466  * exp(q) is defined for pure quaternions (scalar part zero) only.
1467  * (that is, members of the Lie algebra of the quaternion group).
1468  * This function ignores the scalar part - it does not check for zero.
1469  */
1470  friend Quaternion exp(const Quaternion & q)
1471  {
1472  Vector a = q.v;
1473  GLfloat angle = a.length();
1474  return (angle == 0) ?
1475  Quaternion() :
1476  Quaternion(cos(angle), a * sin(angle)/angle);
1477  }
1478 
1479  /**
1480  * exp(v) is a quaternion. The vector is treated as a "pure" quaternion
1481  * (that is, as a member of the Lie algebra of the quaternion group).
1482  */
1483  friend Quaternion exp(const Vector & v)
1484  {
1485  GLfloat angle = v.length();
1486  return (angle == 0) ?
1487  Quaternion() :
1488  Quaternion(cos(angle), v * sin(angle)/angle);
1489  }
1490 
1491 // /**
1492 // * The 'logarithm' of a unit quaternion is a vector.
1493 // * This function is defined because it appears in descriptions of quaternions.
1494 // * Although the name 'ln' is appropriate in some ways, this function must be used with
1495 // * caution because it may not have the properties you expect of a logarithm.
1496 // * For example, \a ln(q1)+ln(q2) makes sense only if \a q1 and \a q2 have the
1497 // * same axis.
1498 // * \pre The quaternion must be a unit quaternion.
1499 // */
1500 // friend Vector ln(const Quaternion & q);
1501 //
1502 // /**
1503 // * The 'exponent' of a vector is a unit quaternion.
1504 // * Although the name 'exp' is appropriate in some ways, this function must be used with
1505 // * caution because it may not have the properties you expect of an exponent.
1506 // * For example, \a exp(v1+v2)=exp(v1)*exp(v2) only if \a v1 and \a v2 have the same
1507 // * direction.
1508 // */
1509 // friend Quaternion exp(const Vector & v);
1510 
1511  /**
1512  * Return the dot product of quaternions \c q and \c r.
1513  * The dot product of \a (s,u) and \a (t,v) is \a st+dot(u,v)
1514  * where \a dot(u,v) denotes the vector dot product of \a u and \a v.
1515  * \return the dot product of quaternions \c q and \c r.
1516  */
1517  friend GLfloat dot(const Quaternion & q, const Quaternion & r);
1518 
1519  /**
1520  * Compare two quaternions.
1521  * This function returns \c true only if corresponding components are exactly equal.
1522  * Values that are theoretically equal but computed in different ways are likely
1523  * to be unequal according to this function.
1524  */
1525  friend bool operator==(const Quaternion & x, const Quaternion & y);
1526 
1527  /**
1528  * Compare two quaternions.
1529  * This function returns \c false only if corresponding components are exactly equal.
1530  * Values that are theoretically equal but computed in different ways are likely
1531  * to be unequal according to this function.
1532  */
1533  friend bool operator!=(const Quaternion & x, const Quaternion & y);
1534 
1535  /**
1536  * Write the quaternion to the output stream as \a s \a (x,y,z).
1537  */
1538  friend std::ostream & operator<<(std::ostream & os, const Quaternion & q);
1539 
1540 private:
1541 
1542  /** Scalar component of quaternion. */
1543  GLfloat s;
1544 
1545  /** Vector component of quaternion. */
1547 };
1548 
1549 
1550 
1551 /**
1552  * An instance represents a camera.
1553  * An instance of class \c Camera is used to control the view.
1554  * The function \c Camera::apply() calls \c gluLookAt() with
1555  * appropriate parameters. The other functions of this class
1556  * set up these parameters.
1557  *
1558  * Camera movements may be smooth (interlpolated between end
1559  * points) or abrupt. The function Camera::setMode() determines
1560  * the kind of movement.
1561  * Smooth transitions are obtained by calling \c Camera::idle()
1562  * in the GLUT idle callback function, together with the various
1563  * camera movement functions.
1564  */
1565 
1566 
1567 
1568 //typedef void (BaseCamera::*IdleMemFunc)();
1569 
1570 //IdleMemFunc gIdleMemFunc;
1571 
1572 /**
1573 * All derived class must implement at least two
1574 * virtual functions \c BaseCamera::idle() which will
1575 * typically be called in the callback function for glutIdleFunc,
1576 * i.e. within callback function "idle()" DerivedClass::idle() will
1577 * be called and later in "main" callback "idle()" will be called
1578 * as parameter to "glutIdleFunc".
1579 * void idle() { DerivedClass::idle();}
1580 * int main() { ... glutIdleFunc(idle); ...}
1581 * \c BaseCamera::apply() const. Similarly inside callback function
1582 * for "glutDisplayFunc", say "display()", DerivedClass::apply() will be
1583 * called.
1584 * i.e. void display() { DerivedClass::apply();..}
1585 * int main(){...glutDisplayFunc(display); ...}
1586 *
1587 */
1588 
1590 {
1591 public:
1592  /** Construct an instance of a \a BaseCamera.
1593  * This constructor is usually called from a subclass.
1594  */
1596  {}
1597 
1598  /**
1599  * Set the number of steps required for a camera movement.
1600  * \param s is the number of steps executed during a movement.
1601  * \a s = 10 will give a rapid, possibly jerky, movement.
1602  * \a s = 100 will give a slow, smooth movement.
1603  */
1604  void setSteps(int s)
1605  {
1606  maxSteps=s;
1607  }
1608 
1609  /**
1610  * This function should be called from the GLUT idle() function
1611  * or its equivalent. It performs one step of the motion until
1612  * the motion is complete, after which it has no effect.
1613  */
1614  virtual void idle()=0;
1615 
1616  /**
1617  * This function should be called from the GLUT display() function
1618  * or its equivalent.
1619  */
1620  virtual void apply() const =0;
1621 
1622  /**
1623  * This function is just a suggested wrapper for all derived class
1624  * for initializations, such as set up first and last position for
1625  * motions in /c Interpolator, or set up new eye and view parameter
1626  * for /c Camera. I don't want to force new class to wrap their
1627  * initialization actions within this function, so, I don't make this
1628  * method as abstract one.
1629  * (added by nick)
1630  */
1631  virtual void update()
1632  {}
1633 
1634 protected:
1635 
1636  /** Current value of step counter. */
1637  int steps;
1638 
1639  /** Maximum number of steps for a smooth movement. */
1641 
1642 };
1643 
1644 
1645 /**
1646  * An instance represents a camera.
1647  * An instance of class \c Camera is used to control the view.
1648  * The function \c Camera::apply() calls \c gluLookAt() with
1649  * appropriate parameters. The other functions of this class
1650  * set up these parameters.
1651  *
1652  * Camera movements may be smooth (interlpolated between end
1653  * points) or abrupt. The function Camera::setMode() determines
1654  * the kind of movement.
1655  * Smooth transitions are obtained by calling \c Camera::idle()
1656  * in the GLUT idle callback function, together with the various
1657  * camera movement functions.
1658  */
1659 class Camera : public BaseCamera
1660 {
1661  //friend void myIdle();
1662 public:
1663 
1664  /**
1665  * Construct a default camera. The view is set as follows:
1666  * Eye = (0,0,1). Model=(0,0,0). Up=(0,1,0).
1667  */
1668  Camera();
1669 
1670  /**
1671  * Construct a camera for a particular view.
1672  * \param eye sets the eye coordinates for \c gluLookAt().
1673  * \param model sets the model coordinates for \c gluLookAt().
1674  * \param up sets the 'up' vector for \c gluLookAt().
1675  */
1676  Camera(const Point & eye, const Point & model, const Vector & up);
1677 
1678  /**
1679  * Construct a camera for a particular view.
1680  * The 'up' vector is set to (0,1,0).
1681  * \param eye sets the eye coordinates for \c gluLookAt().
1682  * \param model sets the model coordinates for \c gluLookAt().
1683  */
1684  Camera(const Point & eye, const Point & model);
1685 
1686  /**
1687  * Construct a camera for a particular view.
1688  * The 'up' vector is set to (0,1,0).
1689  * The model point is set to (0,0,0).
1690  * \param eye sets the eye coordinates for \c gluLookAt().
1691  */
1692  explicit Camera(const Point & eye);
1693 
1694  /**
1695  * Set the camera for a particular view.
1696  * \param eye sets the eye coordinates for \c gluLookAt().
1697  * \param model sets the model coordinates for \c gluLookAt().
1698  * \param up sets the 'up' vector for \c gluLookAt().
1699  */
1700  void set(const Point & eye, const Point & model, const Vector & up)
1701  ;
1702 
1703  /**
1704  * Set the camera for a particular view.
1705  * The 'up' vector is set to (0,1,0).
1706  * \param eye sets the eye coordinates for \c gluLookAt().
1707  * \param model sets the model coordinates for \c gluLookAt().
1708  */
1709  void set(const Point & eye, const Point & model)
1710  ;
1711 
1712  /**
1713  * Set the camera for a particular view.
1714  * The model point is set to (0,0,0).
1715  * The 'up' vector is set to (0,1,0).
1716  * \param eye sets the eye coordinates for \c gluLookAt().
1717  */
1718  void set(const Point & eye)
1719  ;
1720 
1721 
1722  /**
1723  * Update the camera position.
1724  * This function should be called from the GLUT idle() function
1725  * or its equivalent. It performs one step of the motion until
1726  * the motion is complete, after which it has no effect.
1727  */
1728  virtual void idle();
1729 
1730  /**
1731  * Apply the camera position to the model-view matrix.
1732  * This function calls \c gluLookAt() with appropriate parameters.
1733  * It should be called in the GLUT display function or its equivalent
1734  * after the model-view matrix has been initialized.
1735  */
1736  void apply() const;
1737 
1738  /**
1739  * Move the camera upwards (+Y direction).
1740  * \param distance gives the amount of movement. Negative values move
1741  * the camera downwards.
1742  */
1743  void moveUp(GLfloat distance);
1744 
1745  /**
1746  * Move the camera forwards.
1747  * The camera moves towards the model.
1748  * \param distance gives the amount of movement. Negative values move
1749  * the camera away from the model..
1750  */
1751  void moveForward(GLfloat distance);
1752 
1753  /**
1754  * Move the camera to its left.
1755  * \param distance gives the amount of movement. Negative values move
1756  * the camera to its right.
1757  */
1758  void moveLeft(GLfloat distance);
1759 
1760  /**
1761  * Tilt the camera upwards.
1762  * \param angle gives the angle through which the camera should be moved.
1763  * Negative values give a downward tilt.
1764  */
1765  void tiltUp(double angle);
1766 
1767  /**
1768  * Pan the camera to the left.
1769  * \param angle gives the angle through which the camera should be panned.
1770  * Negative values give panning to the right.
1771  */
1772  void panLeft(double angle);
1773 
1774  /**
1775  * Set the kind of motion required.
1776  * \param mode should be set to \c true for smooth movements
1777  * or to \c false for abrupt movements.
1778  */
1779  void setMode(bool mode)
1780  {
1781  smooth = mode;
1782  }
1783 
1784  /**
1785  * Write a representation of the camera to a stream.
1786  * This function displays the current settings of the eye point,
1787  * the model point, and the up vector.
1788  * \param os is a reference to an output stream.
1789  * \param c is a reference to a camera.
1790  */
1791 
1792  friend std::ostream & operator<<(std::ostream & os, const Camera & c);
1793 
1794 protected:
1795 
1796  /** Update the camera position. */
1797  void update(const Point & e, const Point & m);
1798 
1799  /** Eye coordinates for gluLookAt(). */
1801 
1802  /** Previous eye coordinates. */
1804 
1805  /** Updated eye coordinates. */
1807 
1808 
1809  /** Model coordinates for gluLookAt() */
1811 
1812  /** Previous model coordinates */
1814 
1815  /** Updated model coordinates */
1817 
1818  /** Up vector for gluLookAt() */
1820 
1821  /** Mode for motion */
1822  bool smooth;
1823 };
1824 
1825 /**
1826  * An instance is an interpolator for rotations.
1827  * An instance of Interpolator is used to interpolate between two rotations.
1828  * In other words, given two orientations of an object, an interpolator can
1829  * be used to move the object smoothly from one orientation to the other.
1830  * An interpolator is represented by two quaternions representing the
1831  * extreme values of the rotations. When a real number \a t in the interval
1832  * [0,1] is passed to the interpolator, the interpolator constructs a third
1833  * quaternion representing an intermediate orientation. This quaternion can
1834  * be used to generate a rotation matrix or transform the OpenGL model view.
1835  *
1836  * The simplest way to use this class is as follows:
1837  * -# Construct two quaternions, \a q and \a r, corresponding to the
1838  * first and last positions of the desired movement.
1839  * -# Construct an interpolator \a i(q,r).
1840  * -# In the OpenGL display function, call \c i.apply(t), giving
1841  * \a t a sequence of values ranging from 0 to 1.
1842  *
1843  *
1844  */
1846 {
1847 public:
1848 
1849  /**
1850  * Construct an interpolator with dummy values for the quaternions.
1851  * The interpolator may fail if it is used without first setting the
1852  * start and finish quaternions. Use \c Quaternion::set() to change
1853  * the first and last quaternions to useful values.
1854  */
1855  Interpolator();
1856 
1857  /**
1858  * Construct an interpolator to rotate from \c qFirst to \c qLast.
1859  * Report error \c BAD_INTERPOLATOR_ARG if \c qFirst = \c qLast.
1860  */
1861  Interpolator(const Quaternion & qFirst, const Quaternion & qLast);
1862 
1863  /**
1864  * Change the first and last quaternions of an existing interpolator.
1865  * Report error \c BAD_INTERPOLATOR_ARG if \c qFirst = \c qLast.
1866  */
1867  void set(const Quaternion & qFirst, const Quaternion & qLast)
1868  ;
1869 
1870  /**
1871  * Perform the rotation at position \a t, 0 <= \a t <= 1
1872  * by modifying the current OpenGL transformation matrix.
1873  */
1874  void apply(double t) const;
1875 
1876  /**
1877  * Compute the rotation matrix for position \a t, 0 <= \a t <= 1.
1878  */
1879  void getMatrix(double t, GL_Matrix m) const;
1880 
1881  /**
1882  * Return the quaternion for position \a t, 0 <= \a t <= 1.
1883  */
1884  Quaternion getQuaternion(double t) const;
1885 
1886  /**
1887  * Update the Interpolator position.
1888  * This function should be called from the GLUT idle() function
1889  * or its equivalent. It performs one step of the motion until
1890  * the motion is complete, after which it has no effect.
1891  */
1892  virtual void idle();
1893 
1894  /**
1895  * Apply the Interpolator rotation to the model-view matrix.
1896  * This function calls apply(t) with parameters t which is actually steps/maxSteps.
1897  * It should be called in the GLUT display function or its equivalent
1898  * after the model-view matrix has been initialized.
1899  */
1900  virtual void apply() const;
1901 
1902  /**
1903  * Update Interpolator first and last Quaternion.
1904  */
1905  virtual void update()
1906  {
1907  ;
1908  }
1909 
1910 protected:
1911 
1912  /** Initialize the interpolator. */
1913  void initialize();
1914 
1915  /** The quaternion currently in use. */
1917 
1918  /** The start quaternion for the interpolation. */
1920 
1921  /** The final quaternion for the interpolation. */
1923 
1924  /** The angle between the first and last positions. */
1925  double omega;
1926 
1927  /** The sine of the angle between the first and last positions. */
1928  double sinOmega;
1929 
1930  /** The cosine of the angle between the first and last positions. */
1931  double cosOmega;
1932 };
1933 
1934 
1935 
1936 /**
1937  * An instance is an RGB pixel array.
1938  * An instance of PixelMap holds an array that OpenGL can use
1939  * as a texture or to display directly.
1940  *
1941  * This class is implemented so that it does not depend on Windows.
1942  * In principle, it should even work with Linux and other operating
1943  * systems, although this has not been tested thoroughly.
1944  *
1945  * If you want to use a \a BMP image as a texture, the width and height
1946  * must be powers of two. Thus a 256 x 512 \a BMP image is acceptable
1947  * but a 640 x 400 image is not. This restriction does not apply to
1948  * images that are displayed as bitmaps.
1949  *
1950  * Since an instance of \c PixelMap contains pointers, there are memory
1951  * management issues. The destructor deletes pixel and other data
1952  * associated with a pixel map. The copy constructor is declared privately
1953  * and not implemented: this prevents instances being passed by value,
1954  * although they may be passed by reference. Since there is a default
1955  * constructor, you can construct arrays of PixelMap's or pointers to
1956  * PixelMap.
1957  */
1959 {
1960 public:
1961 
1962  /**
1963  * Construct an empty pixel map.
1964  */
1965  PixelMap();
1966 
1967  /**
1968  * Read a pixel map from a file.
1969  * \param bmpFileName is a path to a BMP file.
1970  */
1971  PixelMap(const char *bmpFileName);
1972 
1973  /**
1974  * Construct a pixel map from a region of the pixel buffer.
1975  * \param x is the \a X coordinate of the lower left corner of the region.
1976  * \param y is the \a Y coordinate of the lower left corner of the region.
1977  * \param w is the width of the region in pixels.
1978  * \param h is the height of the region in pixels.
1979  * \note See also PixelMap::read(x, y, w, h).
1980  */
1981  PixelMap(GLint x, GLint y, GLsizei w, GLsizei h);
1982 
1983  /**
1984  * Delete a pixel map.
1985  */
1986  ~PixelMap();
1987 
1988  /**
1989  * Read a BMP file and convert it to a pixel map.
1990  * Previous data associated with this object will be deleted.
1991  * The BMP file must satisfy several criteria if it is to
1992  * be converted successfully. Conversion failure is
1993  * indicated by the following CUGL errors.
1994  * \li \c OPEN_FAILED: the file could not be opened
1995  * \li \c NOT_BMP_FILE: the file is not a BMP file
1996  * \li \c NOT_24_BITS: the format is not 24 bits/pixel
1997  * \li \c COMPRESSED_BMP_FILE: the file is compressed
1998  * \li \c NOT_ENOUGH_MEMORY: there is not enough memory to store the data
1999  *
2000  * OpenGL cannot use a bitmap as a texture if its dimensions are not powers of 2.
2001  * To check whether the bitmap has acceptable dimensions, call \c PixelMap::badSize().
2002  * To convert the bitmap dimensions to acceptable values, call \c PixelMap::rescale().
2003  * \param bmpFileName is the name of the file to be read, with the extension '.bmp'.
2004  */
2005  void read(const char *bmpFileName);
2006 
2007  /**
2008  * Read a pixel map from a region of the framebuffer.
2009  * This function is similar to the constructor with the same parameters,
2010  * but allocates new memory only if necessary.
2011  * \param x is the \a X coordinate of the lower left corner of the region.
2012  * \param y is the \a Y coordinate of the lower left corner of the region.
2013  * \param w is the width of the region in pixels.
2014  * \param h is the height of the region in pixels.
2015  * \param mode is passed to glReadBuffer before reading the pixels.
2016  * \note See also the constructor PixelMap(x, y, w, h).
2017  */
2018  void read(GLint x, GLint y, GLsizei w, GLsizei h, GLenum mode = GL_FRONT);
2019 
2020  /**
2021  * Write a pixel map to an output stream as a \a BMP file.
2022  * \param bmpFileName is the name of the file to be written, with the extension '.bmp'.
2023  */
2024  void write(const char *bmpFileName);
2025 
2026  /**
2027  * Check the dimensions of the bit map.
2028  * If the dimensions are not powers of 2, return \c true.
2029  * If the dimensions of the bitmap are not powers of 2,
2030  * OpenGL cannot use it as a texture.
2031  * You should call \c PixelMap::rescale() to resize the bit map.
2032  */
2033  bool badSize();
2034 
2035  /**
2036  * Rescale a bit map whose dimensions are not powers of 2.
2037  * The new image will be distorted; the amount of distortion depends
2038  * on how much the dimensions have to be altered.
2039  * Use \c PixelMap::badSize() to determine whether the dimensions are powers of 2.
2040  */
2041  void rescale();
2042 
2043  /**
2044  * Draw the pixel map at the current raster position.
2045  * Error \c NO_PIX_MAP if there is no pixel map avaialble.
2046  */
2047  void draw();
2048 
2049  /**
2050  * Set texture parameters for the pixel map.
2051  * \param name is an OpenGL index for the texture parameters
2052  * provided by the caller.
2053  * \note This function sets \c GL_TEXTURE_MAG_FILTER and
2054  * \c GL_TEXTURE_MIN_FILTER to \c GL_NEAREST. Call glTexParameter()
2055  * to change these settings.
2056  * \note When this function returns, OpenGL has copied the pixel map
2057  * into its own memory space. It is therefore safe to delete the
2058  * PixelMap instance after calling setTexture().
2059  */
2060  void setTexture(GLuint name);
2061 
2062  /**
2063  * Set texture parameters for the pixel mipmaps.
2064  * Construct a family of mipmaps for texturing.
2065  * \param name is an OpenGL index for the texture parameters
2066  * provided by the caller.
2067  * \note This function sets \c GL_TEXTURE_MIN_FILTER to
2068  * \c GL_LINEAR_MIPMAP_NEAREST. Call glTexParameter()
2069  * to change this setting.
2070  * \note When this function returns, OpenGL has copied the pixel map
2071  * into its own memory space. It is therefore safe to delete the
2072  * PixelMap instance after calling setMipmaps().
2073  * \note Call this function once only for each texture you need in
2074  * your program. Use \c glBindTexture to select textures in the
2075  * display function.
2076  */
2077  void setMipmaps(GLuint name);
2078 
2079  /** Check that two pixel maps are compatible for combining. */
2080  friend bool compatible(const PixelMap & m1, const PixelMap & m2);
2081 
2082  /** Combine two pixel maps.
2083  * \param m1 is the first map to be combined.
2084  * \param m2 is the second map to be combined.
2085  * \param res is the resulting pixel map.
2086  The caller is responsible for constructing this map;
2087  it is not constructed by the function.
2088  \param prop is the mixing proportion: 0 gives m1,
2089  0.5 gives half of each, and 1 gives m2.
2090  */
2091  friend void mix(const PixelMap & m1, const PixelMap & m2, PixelMap & res, double prop);
2092 
2093  /** Select a region from a pixel map.
2094  * \param src is the pixel map from which the data is extracted.
2095  * \param xp defines the left side of the selected region.
2096  * \param yp defines the right side of the selected region.
2097  * \param width is the width of the selected region.
2098  * \param height is the height of the selected region.
2099  */
2100  void select(const PixelMap & src, int xp, int yp, int width, int height);
2101 
2102  /**
2103  * Return number of rows in pixel map.
2104  */
2105  unsigned long getRows() const
2106  {
2107  return numRows;
2108  }
2109 
2110  /**
2111  * Return number of columns in pixel map.
2112  */
2113  unsigned long getColumns() const
2114  {
2115  return numCols;
2116  }
2117 
2118  /**
2119  * Return bytes of memory used by pixel map.
2120  */
2121  unsigned long getSize() const
2122  {
2123  return size;
2124  }
2125 
2126  /**
2127  * Return name of BMP file.
2128  */
2129  char *getName() const
2130  {
2131  return fileName;
2132  }
2133 
2134  /**
2135  * Return \c true if a pixel map has been read successfully.
2136  */
2137  bool ready() const
2138  {
2139  return pixels != 0;
2140  }
2141 
2142  /**
2143  * Write a description of the pixel map to the output stream.
2144  */
2145  friend std::ostream & operator<<(std::ostream & os, const PixelMap & pm);
2146 
2147 private:
2148 
2149  /**
2150  * The copy constructor is private and unimplemented.
2151  * This prevents pixel maps from being copied by mistake.
2152  */
2153  PixelMap(const PixelMap & pm);
2154 
2155  /** Allocate memory for a new pixel map if necessary. */
2156  bool allocate(unsigned long newSize);
2157 
2158  /** Number of rows in the pixel map. */
2159  unsigned long numRows;
2160 
2161  /** Number of columns in the pixel map. */
2162  unsigned long numCols;
2163 
2164  /** Size, in bytes, of the pixel map. */
2165  unsigned long size;
2166 
2167  /** Name of the file used to store the pixel map. */
2168  char *fileName;
2169 
2170  /** Pointer to the pixels of the map. */
2171  unsigned char *pixels;
2172 };
2173 
2174 
2175 /** The type of an array of GLfloats. */
2176 typedef GLfloat* GLfloatArray;
2177 
2178 /**
2179  * An instance is a surface of revolution represented by its profile.
2180 
2181  * The shape of the surface is determined by a 'profile'.
2182  *
2183  * The profile is defined by an array. Each component of the
2184  * array is a pair \a (h,r) in which \a h is measured along
2185  * the axis of revolution and \a r is the distance from the
2186  * axis. (If the axis is assumed to be vertical, then \a h
2187  * suggests 'height' and \a r suggests 'radius'.)
2188  * The surface is generated by rotating the profile
2189  * about the \a Z-axis.
2190  *
2191  * The function \c Revolute::draw() generates
2192  * vertex coordinates, normals, and texture coordinates for the
2193  * surface.
2194  *
2195  * It is up to the caller to set the OpenGL state for rendering:
2196  * this includes setting material properties and defining rules for polygon shading,
2197  * or binding an appropriate texture.
2198  *
2199  * The normals generated by \c Revolute::process() are obtained by averaging
2200  * the normals of the polygons that meet at each vertex. Consequently,
2201  * if \c GL_SMOOTH shading is used and sufficient points and slices are specified,
2202  * the object should look fairly smooth.
2203  */
2205 {
2206 public:
2207  /**
2208  * Construct a surface of revolution.
2209  *
2210  * \param numSteps is the number of coordinates in the profile.
2211  * \param profile is the address of a 2D array giving the points of the profile.
2212  */
2213  Revolute(int numSteps, GLfloat profile[][2]);
2214 
2215  /**
2216  * Delete a surface of revolution.
2217  */
2218  ~Revolute();
2219 
2220  /**
2221  * Set the number of "slices".
2222  * The value determines the visual quality of the object.
2223  * The number of slices should be an odd number greater than 2.
2224  * If it is not, Revolute::process() will change it.
2225  * By default, the number of slices is 45, corresponding to
2226  * 8 degrees per slice.
2227  * \note After changing the number of slices, you must call
2228  * \c Revolute::process() again before calling \c Revolute::draw().
2229  */
2230  void setSlices(int slices);
2231 
2232  /**
2233  * Set the eccentricity of the surface.
2234  * By default, the eccentricity is 0, giving a surface
2235  * with a circular cross-section. Setting the eccentricity
2236  * to a non-zero value gives a surface with an elliptical
2237  * cross-section. As the eccentricity approaches 1,
2238  * the major axis of the ellipse increases without limit
2239  * as the cross-section approaches a parabola.
2240  * \param ecc must be greater than or equal to zero and
2241  * less than 1.
2242  * \note After changing the eccentricity, you must call
2243  * \c Revolute::process() again before calling \c Revolute::draw().
2244  */
2245  void setEccentricity(double ecc);
2246 
2247  /**
2248  * Compute vertexes, normals, and texture coordinates for the surface of revolution.
2249  * This function must be called \b before calling \c Revolute::draw().
2250  */
2251  void process();
2252 
2253  /**
2254  * Draw the surface of revolution.
2255  * \param showNormals determines whether surface normals will be drawn.
2256  * Note that surface normals are computed for lighting purposes anyway:
2257  * \c showNormals is provided mainly as a debugging aid and should not
2258  * normally be needed.
2259  * \note Revolute::process() must be called before this function.
2260  */
2261  void draw(bool showNormals = false);
2262 
2263 private:
2264 
2265  /**
2266  * The copy constructor is private and not implemented:
2267  * instances cannot be copied implicitly.
2268  */
2269  Revolute(const Revolute &);
2270 
2271  /**
2272  * The assignment operator is private and not implemented:
2273  * instances cannot be assigned.
2274  */
2275  const Revolute& operator=(const Revolute &);
2276 
2277  /** */
2278  int numSteps;
2279 
2280  /** */
2281  int numSlices;
2282 
2283  /** */
2284  double eccentricity;
2285 
2286  /** */
2287  bool ready;
2288 
2289  /** */
2290  GLfloatArray *coor;
2291 
2292  /** */
2293  GLfloat *texCoor;
2294 
2295  /** */
2296  Point *points;
2297 
2298  /** */
2299  Vector *normals;
2300 
2301  /** */
2302  Vector *faceNormals;
2303 };
2304 
2305 
2306 /**
2307  * \defgroup freefun Miscellaneous functions
2308  */
2309 
2310 //@{
2311 
2312 /**
2313  * Convert degrees to radians.
2314  */
2315 inline double radians(double angle)
2316 {
2317  return angle * PI / 180;
2318 }
2319 
2320 /**
2321  * Convert radians to degrees.
2322  */
2323 inline double degrees(double angle)
2324 {
2325  return angle * 180 / PI;
2326 }
2327 
2328 /** Return the square of the argument. */
2329 inline double sqr(double x)
2330 {
2331  return x * x;
2332 }
2333 
2334 /** Return a random integer in [0, max). */
2335 inline unsigned int randInt(unsigned int max)
2336 {
2337  static unsigned int seed = 12345678;
2338  unsigned int result;
2339  const unsigned int bucket = static_cast<unsigned int>(4294967296.0 / max);
2340  do
2341  {
2342  seed = 1664525 * seed + 1013904223;
2343  result = seed / bucket;
2344  }
2345  while (result >= max);
2346  return result;
2347 }
2348 
2349 /** Return a random integer in [-max, max]. */
2350 inline int randSym(unsigned int max)
2351 {
2352  return randInt(2 * max + 1) - max;
2353 }
2354 
2355 /** Return a random double in [0, 1). */
2356 inline double randReal()
2357 {
2358  int BIG = 10000000;
2359  return double(randInt(BIG)) / double(BIG);
2360 }
2361 
2362 /**
2363  * Construct normals for OpenGL triangle strips.
2364  * Given a set of vertexes definining a triangle strip in OpenGL format,
2365  * this functions constructs a normal corresponding to each vertex.
2366  * \param points is an array of points giving the vertex coordinates.
2367  * \param normals is an array of vectors in which the vertex normals will be stored.
2368  * \param numPoints is the number of vertexes provided and the number of normals
2369  * that will be calculated.
2370  * \param neg specifies negated normals, if \a true.
2371  The default is \a false.
2372  * \note To avoid allocation and deallocation overhead, this function uses a
2373  * a fixed amount of workspace that allows up to 100 vertexes to be processed.
2374  * If numPoints > 100, the function will have no effect.
2375  * \note For efficiency, it is better to compute the normals during initialization
2376  * rather than each time the model is displayed.
2377  */
2378 void triStripNormals(Point points[], Vector normals[], int numPoints, bool neg = false);
2379 
2380 /**
2381  * Constructs a surface of revolution.
2382  * Constructs and renders a surface of revolution obtained by rotating
2383  * a curve about the \a Y axis.
2384 
2385  * \param numSteps is the number of points in the array \c coor
2386  * \param coor is the 2D coordinates of points of the profile
2387  * \param numSlices is the number of pie-shaped slices used to render the surface.
2388  * \param drawNormals determines whether normals are generated. By default, normals
2389  * are not generated.
2390 
2391  * For example, if \c numSlices = 20, points will be constructed at 360/20 = 18
2392  * degree intervals.
2393 
2394  * This function constructs an array of points in 3D space and then issues
2395  * calls to \c glVertex(). If \c drawNormals is true, it also issues calls to
2396  * \c glNormal(). The effect of these calls is to define a 3D mesh.
2397  * It is up to the caller to set the OpenGL state for rendering:
2398  * this includes setting material properties and defining rules for polygon shading.
2399 
2400  * The normals generated by \c revolve() are obtained by averaging the normals of the
2401  * polygons that meet at each vertex. Consequently, if \c GL_SMOOTH shading is used
2402  * and enough points are specified, the object should look fairly smooth.
2403 
2404  * \note This function has been replaced by class \c Revolute, which provides more
2405  * functionality and is more efficient.
2406  */
2407 void revolve(int numSteps, GLfloat coor[][2], int numSlices, bool drawNormals = false);
2408 
2409 
2410 
2411 // Additional inline functions for Point and Vector classes.
2412 
2413 /**
2414  * Call gluLookAt() looking at the origin of the model (0,0,0)
2415  * with 'up' vector (0,1,0).
2416  * \param eye is the position of the viewer's eye.
2417  */
2418 inline void lookAt(Point eye)
2419 {
2420  gluLookAt
2421  (
2422  eye[0], eye[1], eye[2],
2423  0, 0, 0,
2424  0, 1, 0
2425  );
2426 }
2427 
2428 /**
2429  * Call gluLookAt() with 'up' vector (0,1,0).
2430  * \param eye is the position of the viewer's eye in model coordinates.
2431  * \param model is the point at the centre of the view in model coordinates.
2432  */
2433 inline void lookAt(Point eye, Point model)
2434 {
2435  gluLookAt
2436  (
2437  eye[0], eye[1], eye[2],
2438  model[0], model[1], model[2],
2439  0, 1, 0
2440  );
2441 }
2442 
2443 /**
2444  * Call gluLookAt().
2445  * \param eye is the position of the viewer's eye in model coordinates.
2446  * \param model is the point at the centre of the view in model coordinates.
2447  * \param up is a vector giving the upwards direction in the model.
2448  */
2449 inline void lookAt(Point eye, Point model, Vector up)
2450 {
2451  gluLookAt
2452  (
2453  eye[0], eye[1], eye[2],
2454  model[0], model[1], model[2],
2455  up[0], up[1], up[2]
2456  );
2457 }
2458 
2459 // End of free functions
2460 //@}
2461 
2462 
2463 /**
2464  * \defgroup model Materials and Models
2465  */
2466 
2467 //@{
2468 
2469 /**
2470  * \todo Models should probably be put into a separate file.
2471  */
2472 
2473 // Axes
2474 
2475 /**
2476  * Draw coordinate axes.
2477  * This function draws the three principal axes in the current
2478  * position, using \c size to determine the length of each axis.
2479  * The axes are colour-coded: \a X = red, \a Y = green, \a Z = blue.
2480  */
2481 void axes(GLfloat size = 1);
2482 
2483 /**
2484  * Draw an aircraft.
2485  * The argument determines whether the plane is drawn with a metallic
2486  * colour (\c shadow = \c false, the default) or black, to act as a
2487  * shadow (\c shadow = \c true).
2488  * The aircraft is built using Bezier surfaces. If you use glScalef
2489  * to change its size, you must enable \c GL_NORMALIZE to correct
2490  * the normals. Otherwise, the lighting will be wrong.
2491  */
2492 void buildPlane(bool shadow = false);
2493 
2494 /**
2495  * Construct a GL call list for the aircraft and return its index.
2496  */
2497 GLuint makePlaneList(bool shadow = false);
2498 
2499 
2500 /**
2501  * Enumeration for materials.
2502  */
2504 {
2505  BLACK, /**< Black. */
2506  WHITE, /**< White. */
2507  RED, /**< Red. */
2508  GREEN, /**< Green. */
2509  BLUE, /**< Blue. */
2510  METAL, /**< General metallic colour.*/
2511  GLASS, /**< General transparent marterial.*/
2512  BRASS, /**< Brass. */
2513  BRONZE, /**< Matt bronze. */
2514  POLISHED_BRONZE, /**< Polished bronze. */
2515  CHROME, /**< Chrome. */
2516  COPPER, /**< Matt copper. */
2517  POLISHED_COPPER, /**< Polished copper. */
2518  GOLD, /**< Matt gold. */
2519  POLISHED_GOLD, /**< Polished gold. */
2520  PEWTER, /**< Pewter. */
2521  SILVER, /**< Matt silver. */
2522  POLISHED_SILVER, /**< Polished silver. */
2523  EMERALD, /**< Emerald. */
2524  JADE, /**< Jade. */
2525  OBSIDIAN, /**< Obsidian. */
2526  PEARL, /**< Pearl. */
2527  RUBY, /**< Ruby. */
2528  TURQUOISE, /**< Turquoise. */
2529  BLACK_PLASTIC, /**< Black plastic. */
2530  BLACK_RUBBER, /**< Black rubber. */
2531  LAST_VALUE
2532 };
2533 
2534 /**
2535  * Set material values from the enumeration.
2536  \param m is chosen from the enumeration \c MATERIAL
2537  \param face should be one of \c GL_FRONT (the default),
2538  \c GL_BACK, or \c GL_FRONT_AND_BACK.
2539  */
2540 void setMaterial(const int m, GLenum face = GL_FRONT);
2541 
2542 // The following array describes material properties.
2543 // ambiance [4],
2544 // diffuse [4],
2545 // specular [4],
2546 // shininess [1].
2547 // 13 values are required to define a material.
2548 
2549 /**
2550  * Add a material to the set of built-in materials.
2551  * The array of material has a fixed size of 100.
2552  * An attempt to create more than 100 materials will fail.
2553  * The parameters specify:
2554  *
2555  * - RGBA values for ambient light
2556  * - RGBA values for diffuse light
2557  * - RGBA values for specular light
2558  * - Value for shininess exponent
2559  * \return the index of the new material.
2560  */
2561 int addMaterial(
2562  GLfloat ambR, GLfloat ambG, GLfloat ambB, GLfloat ambA,
2563  GLfloat difR, GLfloat difG, GLfloat difB, GLfloat difA,
2564  GLfloat speR, GLfloat speG, GLfloat speB, GLfloat speA,
2565  GLfloat shine);
2566 
2567 /**
2568  * Add a material to the set of built-in materials.
2569  * The array of material has a fixed size of 100.
2570  * An attempt to create more than 100 materials will fail.
2571  * \param params specifies:
2572  * - RGBA values for ambient light
2573  * - RGBA values for diffuse light
2574  * - RGBA values for specular light
2575  * - Value for shininess exponent
2576  * \return the index of the new material.
2577  */
2578 int addMaterial(GLfloat params[]);
2579 
2580 // End of free functions
2581 //@}
2582 
2583 //=============================== End of declarations ==============================//
2584 
2585 // Code below this point consists of inline function definitions.
2586 // Functions that are not defined here are defined in cugl.cpp.
2587 
2588 // class Point: inlined constructors and member functions.
2589 
2590 inline Point::Point (GLfloat coordinates[])
2591 {
2592  x = coordinates[0];
2593  y = coordinates[1];
2594  z = coordinates[2];
2595  w = coordinates[3];
2596 }
2597 
2598 inline Point Point::operator+=(const Vector & v)
2599 {
2600  x += w * v.x;
2601  y += w * v.y;
2602  z += w * v.z;
2603  return *this;
2604 }
2605 
2606 inline Point Point::operator-=(const Vector & v)
2607 {
2608  x -= w * v.x;
2609  y -= w * v.y;
2610  z -= w * v.z;
2611  return *this;
2612 }
2613 
2614 inline Point Point::operator/(GLfloat s) const
2615 {
2616  return Point(x, y, z, s * w);
2617 }
2618 
2619 inline void Point::draw() const
2620 {
2621  if (w == 0)
2622  return;
2623  glVertex4f(x, y, z, w);
2624 }
2625 
2626 inline void Point::light(GLenum lightNum) const
2627 {
2628  GLfloat p[4];
2629  p[0] = x;
2630  p[1] = y;
2631  p[2] = z;
2632  p[3] = w;
2633  glLightfv(lightNum, GL_POSITION, p);
2634 }
2635 
2636 inline void Point::translate() const
2637 {
2638  glTranslatef(x/w, y/w, z/w);
2639 }
2640 
2641 // class Point: inlined friend functions.
2642 
2643 inline Point operator+(const Point & p, const Vector & v)
2644 {
2645  return Point(p.x + p.w * v.x, p.y + p.w * v.y, p.z + p.w * v.z, p.w);
2646 }
2647 
2648 inline Point operator+(const Vector & v, const Point & p)
2649 {
2650  return Point(p.x + p.w * v.x, p.y + p.w * v.y, p.z + p.w * v.z, p.w);
2651 }
2652 
2653 inline Point operator*(const Point & p, GLfloat s)
2654 {
2655  return Point(s * p.x, s * p.y, s * p.z, s * p.w);
2656 }
2657 
2658 inline Point operator*(GLfloat s, const Point & p)
2659 {
2660  return Point(s * p.x, s * p.y, s * p.z, s * p.w);
2661 }
2662 
2663 inline bool operator==(const Point & p, const Point & q)
2664 {
2665  return p.x == q.x && p.y == q.y && p.z == q.z && p.w == q.w;
2666 }
2667 
2668 inline bool operator!=(const Point & p, const Point & q)
2669 {
2670  return !(p == q);
2671 }
2672 
2673 inline GLfloat dist(const Point & p, const Plane & s)
2674 {
2675  return p.x * s.a + p.y * s.b + p.z * s.c + p.w * s.d;
2676 }
2677 
2678 inline GLfloat dist(const Plane & s, const Point & p)
2679 {
2680  return s.a * p.x + s.b * p.y + s.c * p.z + s.d * p.w;
2681 }
2682 
2683 // Class Line: inlined member functions.
2684 
2685 inline Line::Line(const Point & p, const Point & q)
2686  : s(p), f(q)
2687 { }
2688 
2689 inline Line::Line(const Point & p, const Vector & v)
2690  : s(p), f(p + v)
2691 { }
2692 
2693 
2694 // Class Line: inlined friend functions.
2695 
2696 inline bool operator==(const Line & m, const Line & n)
2697 {
2698  return m.s == n.s && m.f == n.f;
2699 }
2700 
2701 inline bool operator!=(const Line & m, const Line & n)
2702 {
2703  return !(m == n);
2704 }
2705 
2706 
2707 
2708 // Class Plane: inlined member functions.
2709 
2710 inline Vector Plane::normal() const
2711 {
2712  return Vector(a,b,c).unit();
2713 }
2714 
2715 // Class Plane: inlined friend functions.
2716 
2717 inline bool operator==(const Plane & p, const Plane & q)
2718 {
2719  return p.a == q.a && p.b == q.b && p.c == q.c && p.d == q.d;
2720 }
2721 
2722 inline bool operator!=(const Plane & p, const Plane & q)
2723 {
2724  return !(p == q);
2725 }
2726 
2727 
2728 
2729 // class Vector: inlined constructors
2730 
2731 inline Vector::Vector (GLfloat coordinates[])
2732 {
2733  x = coordinates[0];
2734  y = coordinates[1];
2735  z = coordinates[2];
2736 }
2737 
2738 inline Vector::Vector(const Point & p, const Point & q)
2739 {
2740  if (p.w == 0 || q.w == 0)
2741  {
2742  x = 0;
2743  y = 0;
2744  z = 0;
2745  }
2746  else
2747  {
2748  x = p.x/p.w - q.x/q.w;
2749  y = p.y/p.w - q.y/q.w;
2750  z = p.z/p.w - q.z/q.w;
2751  }
2752 }
2753 
2754 inline Vector::Vector(const Quaternion & q)
2755 {
2756  x = q.v.x;
2757  y = q.v.y;
2758  z = q.v.z;
2759 }
2760 
2761 // class Vector: inlined member functions.
2762 
2764 {
2765  x += v.x;
2766  y += v.y;
2767  z += v.z;
2768  return *this;
2769 }
2770 
2772 {
2773  x -= v.x;
2774  y -= v.y;
2775  z -= v.z;
2776  return *this;
2777 }
2778 
2780 {
2781  return Vector(-x, -y, -z);
2782 }
2783 
2784 inline Vector Vector::operator*=(GLfloat scale)
2785 {
2786  x *= scale;
2787  y *= scale;
2788  z *= scale;
2789  return *this;
2790 }
2791 
2792 inline GLfloat Vector::norm() const
2793 {
2794  return x * x + y * y + z * z;
2795 }
2796 
2797 inline GLfloat Vector::length() const
2798 {
2799  return GLfloat(sqrt(norm()));
2800 }
2801 
2802 inline void Vector::translate() const
2803 {
2804  glTranslatef(x, y, z);
2805 }
2806 
2808 {
2809  return Matrix(
2810  0.0f, z, -y, 0.0f,
2811  -z, 0.0f, x, 0.0f,
2812  y, -x, -0.0f, 0.0f,
2813  0.0f, 0.0f, 0.0f, 1.0f );
2814 }
2815 
2816 inline void Vector::drawNormal() const
2817 {
2818  glNormal3f(x, y, z);
2819 }
2820 
2821 inline void Vector::draw(const Point & p) const
2822 {
2823  glBegin(GL_LINES);
2824  p.draw();
2825  (p + (*this)).draw();
2826  glEnd();
2827 }
2828 
2829 // class Vector: inlined friend functions.
2830 
2831 inline Vector operator-(const Point & p, const Point & q)
2832 {
2833  if (p.w == 0 || q.w == 0)
2834  return Vector();
2835  else
2836  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);
2837 }
2838 
2839 inline Vector operator+(const Vector & u, const Vector & v)
2840 {
2841  return Vector(u.x + v.x, u.y + v.y, u.z + v.z);
2842 }
2843 
2844 inline Vector operator-(const Vector & u, const Vector & v)
2845 {
2846  return Vector(u.x - v.x, u.y - v.y, u.z - v.z);
2847 }
2848 
2849 inline Vector operator*(const Vector & v, GLfloat s)
2850 {
2851  return Vector(s * v.x, s * v.y, s * v.z);
2852 }
2853 
2854 inline Vector operator*(GLfloat s, const Vector & v)
2855 {
2856  return Vector(s * v.x, s * v.y, s * v.z);
2857 }
2858 
2859 inline Vector cross(const Vector & u, const Vector & v)
2860 {
2861  return Vector(
2862  u.y * v.z - u.z * v.y,
2863  u.z * v.x - u.x * v.z,
2864  u.x * v.y - u.y * v.x );
2865 }
2866 
2867 inline Vector operator*(const Vector & u, const Vector & v)
2868 {
2869  return Vector(
2870  u.y * v.z - u.z * v.y,
2871  u.z * v.x - u.x * v.z,
2872  u.x * v.y - u.y * v.x );
2873 }
2874 
2875 inline GLfloat dot(const Vector & u, const Vector & v)
2876 {
2877  return u.x * v.x + u.y * v.y + u.z * v.z;
2878 }
2879 
2880 inline bool operator==(const Vector & u, const Vector & v)
2881 {
2882  return u.x == v.x && u.y == v.y && u.z == v.z;
2883 }
2884 
2885 inline bool operator!=(const Vector & u, const Vector & v)
2886 {
2887  return !(u == v);
2888 }
2889 
2890 
2891 
2892 // Class Matrix: inlined constructors
2893 
2894 inline Matrix::Matrix(const Plane & p)
2895 {
2896  reflect(p);
2897 }
2898 
2899 inline Matrix::Matrix(const Point & lightPos, const Plane & plane)
2900 {
2901  shadow(lightPos, plane);
2902 }
2903 
2905  GLfloat m00, GLfloat m10, GLfloat m20, GLfloat m30,
2906  GLfloat m01, GLfloat m11, GLfloat m21, GLfloat m31,
2907  GLfloat m02, GLfloat m12, GLfloat m22, GLfloat m32,
2908  GLfloat m03, GLfloat m13, GLfloat m23, GLfloat m33 )
2909 {
2910  m[0][0] = m00;
2911  m[1][0] = m10;
2912  m[2][0] = m20;
2913  m[3][0] = m30;
2914  m[0][1] = m01;
2915  m[1][1] = m11;
2916  m[2][1] = m21;
2917  m[3][1] = m31;
2918  m[0][2] = m02;
2919  m[1][2] = m12;
2920  m[2][2] = m22;
2921  m[3][2] = m32;
2922  m[0][3] = m03;
2923  m[1][3] = m13;
2924  m[2][3] = m23;
2925  m[3][3] = m33;
2926 }
2927 
2928 // Class Matrix: inlined member functions
2929 
2930 inline Point Matrix::apply(const Point & p) const
2931 {
2932  return Point
2933  (
2934  m[0][0] * p.x + m[0][1] * p.y + m[0][2] * p.z + m[0][3] * p.w,
2935  m[1][0] * p.x + m[1][1] * p.y + m[1][2] * p.z + m[1][3] * p.w,
2936  m[2][0] * p.x + m[2][1] * p.y + m[2][2] * p.z + m[2][3] * p.w,
2937  m[3][0] * p.x + m[3][1] * p.y + m[3][2] * p.z + m[3][3] * p.w
2938  );
2939 }
2940 
2941 inline void Matrix::apply() const
2942 {
2943  glMultMatrixf(&m[0][0]);
2944 }
2945 
2946 inline GLfloat *Matrix::get()
2947 {
2948  return &m[0][0];
2949 }
2950 
2951 inline GLfloat & Matrix::operator()(int i, int j)
2952 {
2953  return m[i][j];
2954 }
2955 
2956 inline const GLfloat & Matrix::operator()(int i, int j) const
2957 {
2958  return m[i][j];
2959 }
2960 
2962 {
2963  return inv();
2964 }
2965 
2966 inline Vector Matrix::apply(const Vector & v) const
2967 {
2968  // Gives same result as quaternion.
2969  return Vector
2970  (
2971  m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2],
2972  m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2],
2973  m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2]
2974  );
2975 }
2976 
2977 inline Matrix & Matrix::operator/=(GLfloat s)
2978 {
2979  m[0][0] /= s;
2980  m[0][1] /= s;
2981  m[0][2] /= s;
2982  m[0][3] /= s;
2983  m[1][0] /= s;
2984  m[1][1] /= s;
2985  m[1][2] /= s;
2986  m[1][3] /= s;
2987  m[2][0] /= s;
2988  m[2][1] /= s;
2989  m[2][2] /= s;
2990  m[2][3] /= s;
2991  m[3][0] /= s;
2992  m[3][1] /= s;
2993  m[3][2] /= s;
2994  m[3][3] /= s;
2995  return *this;
2996 }
2997 
2998 inline Matrix & Matrix::operator*=(GLfloat s)
2999 {
3000  m[0][0] *= s;
3001  m[0][1] *= s;
3002  m[0][2] *= s;
3003  m[0][3] *= s;
3004  m[1][0] *= s;
3005  m[1][1] *= s;
3006  m[1][2] *= s;
3007  m[1][3] *= s;
3008  m[2][0] *= s;
3009  m[2][1] *= s;
3010  m[2][2] *= s;
3011  m[2][3] *= s;
3012  m[3][0] *= s;
3013  m[3][1] *= s;
3014  m[3][2] *= s;
3015  m[3][3] *= s;
3016  return *this;
3017 }
3018 
3019 // Class Matrix: inlined friend functions
3020 
3021 inline Matrix Matrix::operator+=(const Matrix & rhs)
3022 {
3023  for (int c = 0; c < 4; ++c)
3024  for (int r = 0; r < 4; ++r)
3025  m[c][r] += rhs(c,r);
3026  return *this;
3027 }
3028 
3029 inline Matrix operator+(const Matrix & m, const Matrix & n)
3030 {
3031  Matrix sum(m);
3032  sum += n;
3033  return sum;
3034 }
3035 
3036 inline Matrix Matrix::operator-=(const Matrix & rhs)
3037 {
3038  for (int c = 0; c < 4; ++c)
3039  for (int r = 0; r < 4; ++r)
3040  m[c][r] -= rhs(c,r);
3041  return *this;
3042 }
3043 
3044 inline Matrix operator-(const Matrix & m, const Matrix & n)
3045 {
3046  Matrix sum(m);
3047  sum -= n;
3048  return sum;
3049 }
3050 
3051 inline Matrix Matrix::operator*=(const Matrix & rhs)
3052 {
3053  *this = (*this) * rhs;
3054  return *this;
3055 }
3056 
3057 inline Matrix operator*(const Matrix & m, const Matrix & n)
3058 {
3059  Matrix r;
3060  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);
3061  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);
3062  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);
3063  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);
3064  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);
3065  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);
3066  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);
3067  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);
3068  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);
3069  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);
3070  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);
3071  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);
3072  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);
3073  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);
3074  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);
3075  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);
3076  return r;
3077 }
3078 
3079 inline bool operator==(const Matrix & m, const Matrix & n)
3080 {
3081  for (int i = 0; i < 4; i++)
3082  for (int j = 0; j < 4; j++)
3083  if (m(i,j) != n(i,j))
3084  return false;
3085  return true;
3086 }
3087 
3088 inline bool operator!=(const Matrix & m, const Matrix & n)
3089 {
3090  for (int i = 0; i < 4; i++)
3091  for (int j = 0; j < 4; j++)
3092  if (m(i,j) != n(i,j))
3093  return true;
3094  return false;
3095 }
3096 
3097 inline Matrix operator*(GLfloat s, const Matrix & m)
3098 {
3099  Matrix sm;
3100  for (int i = 0; i < 4; i++)
3101  for (int j = 0; j < 4; j++)
3102  sm(i, j) = s * m(i, j);
3103  return sm;
3104 }
3105 
3106 inline Matrix operator*(const Matrix & m, GLfloat s)
3107 {
3108  Matrix ms;
3109  for (int i = 0; i < 4; i++)
3110  for (int j = 0; j < 4; j++)
3111  ms(i, j) = s * m(i, j);
3112  return ms;
3113 }
3114 
3115 inline Matrix operator/(const Matrix & m, GLfloat s)
3116 {
3117  Matrix md = m;
3118  return md /= s;
3119 }
3120 
3121 
3122 // Class Quaternion: inlined member functions.
3123 
3125 {
3126  s += q.s;
3127  v += q.v;
3128  return *this;
3129 }
3130 
3132 {
3133  s -= q.s;
3134  v -= q.v;
3135  return *this;
3136 }
3137 
3139 {
3140  v *= x;
3141  s *= x;
3142  return *this;
3143 }
3144 
3146 {
3147  v /= x;
3148  s /= x;
3149  return *this;
3150 }
3151 
3152 inline Vector Quaternion::apply(const Vector & w) const
3153 {
3154  return Vector
3155  (
3156  -(-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])
3157  - 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]),
3158  -(-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])
3159  - 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]),
3160  -(-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])
3161  - 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])
3162  );
3163 }
3164 
3166 {
3167  return v;
3168 }
3169 
3170 inline GLfloat Quaternion::scalar() const
3171 {
3172  return s;
3173 }
3174 
3175 inline GLfloat Quaternion::norm() const
3176 {
3177  return s * s + v.norm();
3178 }
3179 
3180 inline GLfloat Quaternion::magnitude() const
3181 {
3182  return GLfloat(sqrt(norm()));
3183 }
3184 
3186 {
3187  return Quaternion(s, -v);
3188 }
3189 
3190 inline Vector Quaternion::axis() const
3191 {
3192  return v.unit();
3193 }
3194 
3195 inline double Quaternion::angle() const
3196 {
3197  return 2 * acos(s);
3198 }
3199 
3201 {
3202  return inv();
3203 }
3204 
3206 {
3207  GLfloat ns = s * q.s - v[0] * q.v[0] - v[1] * q.v[1] - v[2] * q.v[2];
3208  v = Vector(
3209  q.s * v[0] + s * q.v[0] + v[1] * q.v[2] - v[2] * q.v[1],
3210  q.s * v[1] + s * q.v[1] + v[2] * q.v[0] - v[0] * q.v[2],
3211  q.s * v[2] + s * q.v[2] + v[0] * q.v[1] - v[1] * q.v[0] );
3212  s = ns;
3213  return *this;
3214 
3215 }
3216 
3217 // class Quaternion: inlined friend functions.
3218 
3219 inline GLfloat dot(const Quaternion & q, const Quaternion & r)
3220 {
3221  return q.s * r.s + dot(q.v, r.v);
3222 }
3223 
3224 inline Quaternion operator+(const Quaternion & q, const Quaternion & r)
3225 {
3226  return Quaternion(q.s + r.s, q.v + r.v);
3227 }
3228 
3229 inline Quaternion operator-(const Quaternion & q, const Quaternion & r)
3230 {
3231  return Quaternion(q.s - r.s, q.v - r.v);
3232 }
3233 
3234 inline Quaternion operator*(const Quaternion & q, const Quaternion & r)
3235 {
3236  return Quaternion
3237  (
3238  q.s * r.s - q.v[0] * r.v[0] - q.v[1] * r.v[1] - q.v[2] * r.v[2],
3239  r.s * q.v[0] + q.s * r.v[0] + q.v[1] * r.v[2] - q.v[2] * r.v[1],
3240  r.s * q.v[1] + q.s * r.v[1] + q.v[2] * r.v[0] - q.v[0] * r.v[2],
3241  r.s * q.v[2] + q.s * r.v[2] + q.v[0] * r.v[1] - q.v[1] * r.v[0]
3242  );
3243 }
3244 
3245 inline Quaternion operator*(const Vector & v, const Quaternion & q)
3246 {
3247  return Quaternion
3248  (
3249  - v[0] * q.v[0] - v[1] * q.v[1] - v[2] * q.v[2],
3250  q.s * v[0] + v[1] * q.v[2] - v[2] * q.v[1],
3251  q.s * v[1] + v[2] * q.v[0] - v[0] * q.v[2],
3252  q.s * v[2] + v[0] * q.v[1] - v[1] * q.v[0]
3253  );
3254 }
3255 
3256 inline Quaternion operator*(const Quaternion & q, const Vector & v)
3257 {
3258  return Quaternion
3259  (
3260  - q.v[0] * v[0] - q.v[1] * v[1] - q.v[2] * v[2],
3261  q.s * v[0] + q.v[1] * v[2] - q.v[2] * v[1],
3262  q.s * v[1] + q.v[2] * v[0] - q.v[0] * v[2],
3263  q.s * v[2] + q.v[0] * v[1] - q.v[1] * v[0]
3264  );
3265 }
3266 
3268 {
3269  GLfloat den = q.norm();
3270  GLfloat ns = (s * q.s + v[0] * q.v[0] + v[1] * q.v[1] + v[2] * q.v[2]) / den;
3271  v = Vector
3272  (
3273  (q.s * v[0] - s * q.v[0] - v[1] * q.v[2] + v[2] * q.v[1]) / den,
3274  (q.s * v[1] - s * q.v[1] - v[2] * q.v[0] + v[0] * q.v[2]) / den,
3275  (q.s * v[2] - s * q.v[2] - v[0] * q.v[1] + v[1] * q.v[0]) / den
3276  );
3277  s = ns;
3278  return *this;
3279 }
3280 
3281 inline Quaternion operator*(const Quaternion & q, GLfloat a)
3282 {
3283  return Quaternion(a * q.s, a * q.v);
3284 }
3285 
3286 inline Quaternion operator*(GLfloat a, const Quaternion & q)
3287 {
3288  return Quaternion(a * q.s, a * q.v);
3289 }
3290 
3291 inline bool operator==(const Quaternion & q, const Quaternion & r)
3292 {
3293  return q.s == r.s && q.v == r.v;
3294 }
3295 
3296 inline bool operator!=(const Quaternion & q, const Quaternion & r)
3297 {
3298  return !(q == r);
3299 }
3300 
3301 
3302 
3303 
3304 
3305 // class Interpolator: inline member functions
3306 
3307 inline void Interpolator::getMatrix(double t, GL_Matrix m) const
3308 {
3309  getQuaternion(t).matrix(m);
3310 }
3311 
3312 }
3313 ; // end of namespace
3314 
3315 #endif
3316 
3317