home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / VOGLE.ZIP / VOGLE / SRC / VIEWING.C < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-11  |  7.8 KB  |  363 lines

  1. #include "vogle.h"
  2.  
  3. #ifdef    TC
  4.  
  5. extern    double    cos();
  6. extern    double    sin();
  7. extern    double    asin();
  8. extern    double    sqrt();
  9. extern    double    fabs();
  10.  
  11. #else 
  12.  
  13. #include <math.h>
  14.  
  15. #endif
  16.  
  17. /*
  18.  * NOTE: the words hither and yon are used in this file instead of near and far
  19.  * as they are keywords on some PC compilers (groan). Change them back at your 
  20.  * on peril.
  21.  */
  22.  
  23. #define    SQ(a)    ((a)*(a))
  24. #define COT(a)    ((float)(cos((double)(a)) / sin((double)(a))))
  25.  
  26. /*
  27.  * polarview
  28.  *
  29.  * Specify the viewer's position in polar coordinates by giving
  30.  * the distance from the viewpoint to the world origin, 
  31.  * the azimuthal angle in the x-y plane, measured from the y-axis,
  32.  * the incidence angle in the y-z plane, measured from the z-axis,
  33.  * and the twist angle about the line of sight.
  34.  *
  35.  */
  36. void
  37. polarview(dist, azim, inc, twist)
  38.     float    dist, azim, inc, twist;
  39. {
  40.     if (!vdevice.initialised) 
  41.         verror("polarview: vogle not initialised");
  42.  
  43.     translate(0.0, 0.0, -dist);
  44.     rotate(-twist, 'z');
  45.     rotate(-inc, 'x');
  46.     rotate(-azim, 'z');
  47. }
  48.  
  49. /*
  50.  * up
  51.  *
  52.  *    set the up vector
  53.  */
  54. void
  55. up(x, y, z)
  56.     float    x, y, z;
  57. {
  58.     vdevice.upset = 1;
  59.  
  60.     vdevice.upvector[V_X] = x;
  61.     vdevice.upvector[V_Y] = y;
  62.     vdevice.upvector[V_Z] = z;
  63. }
  64.  
  65. /*
  66.  * normallookat
  67.  *
  68.  *    do the standard lookat transformation.
  69.  */
  70. static void
  71. normallookat(vx, vy, vz, px, py, pz)
  72.     float  vx, vy, vz, px, py, pz;
  73.  
  74. {
  75.     float    l2, l3, sintheta, sinphi, costheta, cosphi;
  76.     Matrix    tmp;
  77.  
  78.     l2 = sqrt((double)(SQ((px - vx)) + SQ((pz - vz))));
  79.     l3 = sqrt((double)(SQ((px - vx)) + SQ((py - vy)) + SQ((pz - vz))));
  80.  
  81.     if (l3 != 0.0) {
  82.         sinphi = (vy - py) / l3;
  83.         cosphi = l2 / l3;
  84.  
  85.         /*
  86.          * Rotate about X by phi
  87.          */
  88.         identmatrix(tmp);
  89.         tmp[1][1] = tmp[2][2] = cosphi;
  90.         tmp[1][2] = sinphi;
  91.         tmp[2][1] = -sinphi;
  92.         multmatrix(tmp);
  93.     }
  94.  
  95.     if (l2 != 0.0) {
  96.         sintheta = (px - vx) / l2;
  97.         costheta = (vz - pz) / l2;
  98.  
  99.         /*
  100.          * Rotate about Y by theta
  101.          */
  102.         identmatrix(tmp);
  103.         tmp[0][0] = tmp[2][2] = costheta;
  104.         tmp[0][2] = -sintheta;
  105.         tmp[2][0] = sintheta;
  106.         multmatrix(tmp);
  107.     }
  108. }
  109.  
  110. /*
  111.  * lookatwithup
  112.  *
  113.  *    do the standard lookat transformation using an up vector as well.
  114.  */
  115. static void
  116. lookatwithup(vx, vy, vz, px, py, pz)
  117.     float  vx, vy, vz, px, py, pz;
  118. {
  119.     Vector    t, u, s;
  120.     Matrix    tmp;
  121.     double    dy, dz, lt, lu;
  122.  
  123.     t[V_X] = vx - px;
  124.     t[V_Y] = vy - py;
  125.     t[V_Z] = vz - pz;
  126.  
  127.     u[V_X] = vdevice.upvector[V_X];
  128.     u[V_Y] = vdevice.upvector[V_Y];
  129.     u[V_Z] = vdevice.upvector[V_Z];
  130.  
  131.     printf("lookatwithup: (%f %f %f),  (%f %f %f),  (%f %f %f)\n", vx, vy, vz, pz, py, pz, u[0], u[1], u[2]);
  132.  
  133.     lt = sqrt(t[V_X] * t[V_X] + t[V_Y] * t[V_Y] + t[V_Z] * t[V_Z]);
  134.  
  135.     if (lt == 0.0)
  136.         verror("vogle: can't have eyepoint and reference point the same in lookat.\n");
  137.  
  138.     lu = sqrt(u[V_X] * u[V_X] + u[V_Y] * u[V_Y] + u[V_Z] * u[V_Z]);
  139.  
  140.     if (lu == 0.0)
  141.         verror("vogle: invalid up vector in lookat.\n");
  142.  
  143.     /*
  144.      * normalise t and u
  145.      */
  146.     t[V_X] /= lt;
  147.     t[V_Y] /= lt;
  148.     t[V_Z] /= lt;
  149.  
  150.     u[V_X] /= lu;
  151.     u[V_Y] /= lu;
  152.     u[V_Z] /= lu;
  153.  
  154.     dz = t[V_X] * u[V_X] + t[V_Y] * u[V_Y] + t[V_Z] * u[V_Z];
  155.  
  156.     if (fabs(dz) >= 1.0)
  157.         verror("vogle: up vector and direction of view are the same.\n");
  158.  
  159.     dy = sqrt(1.0 - dz * dz);
  160.  
  161.     /*
  162.      * calculate view up
  163.      */
  164.     u[V_X] = (u[V_X] - dz * t[V_X]) / dy;
  165.     u[V_Y] = (u[V_Y] - dz * t[V_Y]) / dy;
  166.     u[V_Z] = (u[V_Z] - dz * t[V_Z]) / dy;
  167.  
  168.     /*
  169.      * calculate side vector (cross product of u and t)
  170.      */
  171.     s[V_X] = u[V_Y] * t[V_Z] - u[V_Z] * t[V_Y];
  172.     s[V_Y] = u[V_Z] * t[V_X] - u[V_X] * t[V_Z];
  173.     s[V_Z] = u[V_X] * t[V_Y] - u[V_Y] * t[V_X];
  174.  
  175.     identmatrix(tmp);
  176.  
  177.     tmp[0][0] = s[V_X];
  178.     tmp[1][0] = s[V_Y];
  179.     tmp[2][0] = s[V_Z];
  180.  
  181.     tmp[0][1] = u[V_X];
  182.     tmp[1][1] = u[V_Y];
  183.     tmp[2][1] = u[V_Z];
  184.  
  185.     tmp[0][2] = t[V_X];
  186.     tmp[1][2] = t[V_Y];
  187.     tmp[2][2] = t[V_Z];
  188.  
  189.     multmatrix(tmp);
  190. }
  191.  
  192. /*
  193.  * lookat
  194.  *
  195.  * Specify the viewer's position by giving a viewpoint and a 
  196.  * reference point in world coordinates. A twist about the line
  197.  * of sight may also be given. 
  198.  */
  199. void
  200. lookat(vx, vy, vz, px, py, pz, twist)
  201.     float  vx, vy, vz, px, py, pz, twist;
  202. {
  203.     if (!vdevice.initialised) 
  204.         verror("lookat: vogle not initialised");
  205.  
  206.     rotate(-twist, 'z');
  207.  
  208.     if (vdevice.upset)
  209.         lookatwithup(vx, vy, vz, px, py, pz);
  210.     else
  211.         normallookat(vx, vy, vz, px, py, pz);
  212.  
  213.     translate(-vx, -vy, -vz);
  214. }
  215.  
  216. /*
  217.  * perspective
  218.  *
  219.  * Specify a perspective viewing pyramid in world coordinates by
  220.  * giving a field of view, aspect ratio, and the locations of the 
  221.  * near(hither) and far(yon) clipping planes in the z direction.
  222.  */
  223. void
  224. perspective(fov, aspect, hither, yon)
  225.     float     fov, aspect, hither, yon;
  226. {
  227.     Matrix        mat;
  228.  
  229.     if (!vdevice.initialised)
  230.         verror("perspective: vogle not initialised");
  231.  
  232.     if (aspect == 0.0)
  233.         verror("perspective: can't have zero aspect ratio!");
  234.  
  235.     if ((yon - hither) == 0.0)
  236.         verror("perspective: near clipping plane same as far one.");
  237.  
  238.     if (fov == 0.0 || fov == 180.0)
  239.         verror("perspective: bad field of view passed.");
  240.  
  241.     identmatrix(mat);
  242.  
  243.     mat[0][0] = COT((D2R * fov / 2.0)) / aspect;
  244.     mat[1][1] = COT((D2R * fov / 2.0));
  245.  
  246.     mat[2][2] = -(yon + hither) / (yon - hither);
  247.     mat[2][3] = -1;
  248.     mat[3][2] = -2.0 * yon * hither / (yon - hither);
  249.     mat[3][3] = 0;
  250.  
  251.     loadmatrix(mat);
  252. }
  253.  
  254. /*
  255.  * window
  256.  *
  257.  * Specify a perspective viewing pyramid in world coordinates by
  258.  * giving a rectangle at the near clipping plane and the location
  259.  * of the far clipping plane.
  260.  *
  261.  */
  262. void
  263. window(left, right, bottom, top, hither, yon)
  264.     float     left, right, bottom, top, hither, yon;
  265. {
  266.     Matrix        mat;
  267.  
  268.     if (!vdevice.initialised)
  269.         verror("window: vogle not initialised");
  270.  
  271.     if ((right - left) == 0.0)
  272.         verror("window: left clipping plane same as right one.");
  273.  
  274.     if ((top - bottom) == 0.0)
  275.         verror("window: bottom clipping plane same as top one.");
  276.  
  277.     if ((yon - hither) == 0.0)
  278.         verror("window: near clipping plane same as far one.");
  279.  
  280.     identmatrix(mat);
  281.  
  282.     mat[0][0] = 2.0 * hither / (right - left);
  283.     mat[1][1] = 2.0 * hither / (top - bottom);
  284.     mat[2][0] = (right + left) / (right - left);
  285.     mat[2][1] = (top + bottom) / (top - bottom);
  286.     mat[2][2] = -(yon + hither) / (yon - hither);
  287.     mat[2][3] = -1.0;
  288.     mat[3][2] = -2.0 * yon * hither / (yon - hither);
  289.     mat[3][3] = 0.0;
  290.  
  291.     loadmatrix(mat);
  292. }
  293.  
  294. /*
  295.  * ortho
  296.  *
  297.  * Define a three dimensional viewing box by giving the left,
  298.  * right, bottom and top clipping plane locations and the distances
  299.  * along the line of sight to the near and far clipping planes.
  300.  *
  301.  */
  302. void
  303. ortho(left, right, bottom, top, hither, yon)
  304.     float     left, right, bottom, top, hither, yon;
  305. {
  306.     Matrix        mat;
  307.  
  308.     if (!vdevice.initialised)
  309.         verror("ortho: vogle not initialised");
  310.  
  311.     if ((right - left) == 0.0)
  312.         verror("ortho: left clipping plane same as right one.");
  313.  
  314.     if ((top - bottom) == 0.0)
  315.         verror("ortho: bottom clipping plane same as top one.");
  316.  
  317.     if ((yon - hither) == 0.0)
  318.         verror("ortho: near clipping plane same as far one.");
  319.  
  320.     identmatrix(mat);
  321.  
  322.     mat[0][0] = 2.0 / (right - left);
  323.     mat[1][1] = 2.0 / (top - bottom);
  324.     mat[2][2] = -2.0 / (yon - hither);
  325.     mat[3][0] = -(right + left) / (right - left);
  326.     mat[3][1] = -(top + bottom) / (top - bottom);
  327.     mat[3][2] = -(yon + hither) / (yon - hither);
  328.  
  329.     loadmatrix(mat);
  330. }
  331.  
  332. /*
  333.  * ortho2
  334.  *
  335.  * Specify a two dimensional viewing rectangle. 
  336.  *
  337.  */
  338. void
  339. ortho2(left, right, bottom, top)
  340.     float    left, right, bottom, top;
  341. {
  342.     Matrix    mat;
  343.  
  344.     if (!vdevice.initialised) 
  345.         verror("ortho2: vogle not initialised");
  346.  
  347.     identmatrix(mat);
  348.  
  349.     if ((right - left) == 0.0)
  350.         verror("ortho2: left clipping plane same as right one.");
  351.  
  352.     if ((top - bottom) == 0.0)
  353.         verror("ortho2: bottom clipping plane same as top one.");
  354.  
  355.     mat[0][0] = 2.0 / (right - left);
  356.     mat[1][1] = 2.0 / (top - bottom);
  357.     mat[2][2] = -1.0;
  358.     mat[3][0] = -(right + left) / (right - left);
  359.     mat[3][1] = -(top + bottom) / (top - bottom);
  360.  
  361.     loadmatrix(mat);
  362. }
  363.