home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / openstep / mesaview / mesadraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  7.8 KB  |  306 lines

  1. #include "mesadraw.h"
  2. #include <3d.h>
  3.  
  4. extern void perpnorm(GLdouble[3],GLdouble[3],GLdouble[3],GLdouble[3]);
  5. extern unsigned long random();
  6. extern void bcopy(void*,void*,unsigned long);
  7.  
  8. #define DIM 30
  9. #define MAX_HEIGHT (300/DIM)
  10. #define RADS(x) ((x)/57.29577951)
  11.  
  12. static GLdouble mesh[DIM][DIM][3];
  13. static GLubyte cols[DIM][DIM][3];
  14.  
  15. /*
  16.  * Create a random matrix of heights and colours
  17.  */
  18.  
  19. void make_matrix(void)
  20. {
  21.   int i,j;
  22.  
  23.   for(i=0;i<DIM;i++)
  24.     for(j=0;j<DIM;j++)
  25.      {
  26.         mesh[i][j][0]=((100.0*i)/(DIM-1.0))-50.0;
  27.         mesh[i][j][2]=((100.0*j)/(DIM-1.0))-50.0;
  28.         mesh[i][j][1]=(random()%MAX_HEIGHT);
  29.        cols[i][j][0]=(mesh[i][j][1]*255)/MAX_HEIGHT;
  30.        cols[i][j][1]=255-cols[i][j][0];
  31.        cols[i][j][2]=0;
  32.      }
  33. }
  34.  
  35. /*
  36.  * Initialise the OpenGL stuff
  37.  */
  38.  
  39. void my_init (float w, float h) 
  40. {
  41.   GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
  42.   GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
  43.   GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  44.   GLfloat light_position[] = { 5.0, 3.0, 9.0, 0.0 };
  45.  
  46.   glMatrixMode (GL_PROJECTION);
  47.   glLoadIdentity ();
  48.   glMatrixMode (GL_MODELVIEW);
  49.   glLoadIdentity ();
  50.  
  51.   glShadeModel(GL_SMOOTH);
  52.  
  53.   glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
  54.   glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  55.   glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
  56.   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  57.  
  58.   glEnable(GL_LIGHT0);
  59.   glEnable(GL_LIGHTING);
  60.  
  61.   glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
  62.   glEnable(GL_COLOR_MATERIAL);
  63.  
  64.   glViewport(0,0,w,h);
  65.   glMatrixMode (GL_PROJECTION);
  66.   gluPerspective (60.0, w/h, 1.0, 400.0);
  67.  
  68.   glEnable(GL_DEPTH_TEST);
  69. }
  70.  
  71. /*
  72.  * Set the viewpoint
  73.  */
  74.  
  75. void set_viewpoint(float zoomDist, float elevAngle, float spinAngle, int white)
  76. {
  77.     float flat_radius, x, y, z, xl, zl;
  78.     flat_radius=zoomDist*cos(RADS(elevAngle));
  79.     x=0.0-(flat_radius*sin(RADS(spinAngle)));
  80.     xl=50.0*sin(RADS(spinAngle));
  81.     z=flat_radius*cos(RADS(spinAngle));
  82.     zl= -50.0*cos(RADS(spinAngle));
  83.     y=zoomDist*sin(RADS(elevAngle));
  84.  
  85.     if(white)
  86.      glClearColor(1,1,1,1);
  87.     else
  88.      glClearColor(0,0,0,1);
  89.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  90.     glMatrixMode (GL_MODELVIEW);
  91.     glLoadIdentity ();
  92. /*
  93.  * we make a somewhat spurious "up" vector because we know we are 
  94.  * looking at the origin and that it's mapped into the plane of
  95.  * the screen anyway so the percise direction is irrelevent.
  96.  */
  97.     gluLookAt (x, y, z,
  98.                0, 0, 0,
  99.                xl, 50, zl);
  100. }
  101.  
  102. /*
  103.  * Get a normal to a corner of a quad.
  104.  */
  105.  
  106. void get_quad_normal(int x, int z, int cx, int cz, GLdouble n[3])
  107. {
  108.         GLdouble *c1, *c2, *c3, *c4;
  109.         c1 = &mesh[x][z][0];
  110.         c2 = &mesh[x+1][z][0];
  111.         c3 = &mesh[x+1][z+1][0];
  112.         c4 = &mesh[x][z+1][0];
  113.         if((cx==0) && (cz==0))
  114.          return perpnorm(c4,c1,c2,n);
  115.         if((cx==0) && (cz==0))
  116.          return perpnorm(c4,c1,c2,n);
  117.         if((cx==1) && (cz==0))
  118.           return perpnorm(c1,c2,c3,n);
  119.         if((cx==1) && (cz==1))
  120.           return perpnorm(c2,c3,c4,n);
  121.         if((cx==0) && (cz==1))
  122.           return perpnorm(c3,c4,c1,n);
  123. }
  124.  
  125. /*
  126.  * Get a normal to a plane as the average of
  127.  * the normals at the four corners of the quad.
  128.  */
  129.  
  130. void get_plane_normal(int x, int z, GLdouble n[3])
  131. {
  132.    GLdouble total[3]={0,0,0};
  133.    get_quad_normal(x,z,0,0,n);
  134.    add3(total,n,total);
  135.    get_quad_normal(x,z,0,1,n);
  136.    add3(total,n,total);
  137.    get_quad_normal(x,z,1,0,n);
  138.    add3(total,n,total);
  139.    get_quad_normal(x,z,1,1,n);
  140.    add3(total,n,total);
  141.    normalize(total);
  142.    n[0]=total[0];
  143.    n[1]=total[1];
  144.    n[2]=total[2];
  145. }
  146.  
  147. /*
  148.  * Get a normal to a point as the average
  149.  * of the surrounding quads.
  150.  */
  151.  
  152. void get_vertex_normal(int x, int z, GLdouble n[3])
  153. {
  154.    GLdouble total[3]={0,0,0};
  155.    if((x>0) && (z>0))
  156.     {
  157.      get_quad_normal(x-1,z-1,1,1,n);
  158.      add3(total,n,total);
  159.     }
  160.    if((x>0) && (z<(DIM-1)))
  161.     {
  162.      get_quad_normal(x-1,z,1,0,n);
  163.      add3(total,n,total);
  164.     }
  165.    if((x<(DIM-1)) && (z>0))
  166.     {
  167.      get_quad_normal(x,z-1,0,1,n);
  168.      add3(total,n,total);
  169.     }
  170.    if((x<(DIM-1)) && (z<(DIM-1)))
  171.     {
  172.      get_quad_normal(x,z,0,0,n);
  173.      add3(total,n,total);
  174.     }
  175.    normalize(total);
  176.    n[0]=total[0];
  177.    n[1]=total[1];
  178.    n[2]=total[2];
  179. }
  180.  
  181. /*
  182.  * Draw the scene
  183.  */
  184.  
  185. void draw_scene(int av)
  186. {
  187.     int xstrip, zrow;
  188.     for(xstrip=0;xstrip<DIM-1;xstrip++)
  189.      {
  190.       glBegin(GL_QUADS);
  191.       for(zrow=0;zrow<DIM-1;zrow++)
  192.        {
  193.         GLdouble *c1, *c2, *c3, *c4;
  194.         GLdouble n1[3], n2[3], n3[3], n4[3];
  195.         int passes,toggle;
  196.         c1 = &mesh[xstrip][zrow][0];
  197.         c2 = &mesh[xstrip+1][zrow][0];
  198.         c3 = &mesh[xstrip+1][zrow+1][0];
  199.         c4 = &mesh[xstrip][zrow+1][0];
  200.         if(av)
  201.          {
  202.           get_vertex_normal(xstrip,zrow,n1);
  203.           get_vertex_normal(xstrip+1,zrow,n2);
  204.           get_vertex_normal(xstrip+1,zrow+1,n3);
  205.           get_vertex_normal(xstrip,zrow+1,n4);
  206.          }
  207.         else
  208.          {
  209.           get_plane_normal(xstrip,zrow,n1);
  210.           bcopy(n1,n2,3*sizeof(GLdouble));
  211.           bcopy(n1,n3,3*sizeof(GLdouble));
  212.           bcopy(n1,n4,3*sizeof(GLdouble));
  213.          }
  214.  
  215.         /*
  216.          * we do this to draw the quads in the opposite direction for
  217.          * each strip as this reduces the effects of the triangluarisation
  218.          * of the quad by the rendering algorithm.
  219.          */
  220.         for(passes=0;passes<4;passes++)
  221.          {
  222.          if((xstrip&1) == (zrow&1))
  223.           toggle=3-passes;
  224.          else
  225.           toggle=passes;
  226.          switch (toggle)
  227.           {
  228.           case 0:
  229.            glColor3ubv(&cols[xstrip][zrow][0]);
  230.            glNormal3dv(n1);
  231.            glVertex3dv(c1);
  232.            break;
  233.  
  234.           case 1:
  235.            glColor3ubv(&cols[xstrip+1][zrow][0]);
  236.            glNormal3dv(n2);
  237.            glVertex3dv(c2);
  238.            break;
  239.  
  240.           case 2:
  241.            glColor3ubv(&cols[xstrip+1][zrow+1][0]);
  242.            glNormal3dv(n3);
  243.            glVertex3dv(c3);
  244.            break;
  245.    
  246.           case 3:
  247.            glColor3ubv(&cols[xstrip][zrow+1][0]);
  248.            glNormal3dv(n4);
  249.            glVertex3dv(c4);
  250.            break;
  251.           }
  252.          }
  253.        }
  254.       glEnd();
  255.      }
  256. }
  257.  
  258. /*
  259.  * We use the display postscript operators to send
  260.  * an outline of the base area directly into the window
  261.  * by projecting points and drawing lines. We also draw
  262.  * a small arrow representing "north" to hep orientation.
  263.  */
  264.  
  265. void outline_scene(void)
  266. {
  267.     GLdouble model[16], proj[16];
  268.     GLint viewport[4];
  269.     GLdouble winx, winy, winz;
  270.  
  271.     glGetDoublev(GL_MODELVIEW_MATRIX, model);
  272.     glGetDoublev(GL_PROJECTION_MATRIX, proj);
  273.     glGetIntegerv(GL_VIEWPORT, viewport);
  274.  
  275.     /* Having got these we can draw the base */
  276.     PSnewpath();
  277.     gluProject(-50.0, 0, -50.0, model, proj, viewport, &winx, &winy, &winz);
  278.     PSmoveto(winx,winy);
  279.     gluProject(50.0, 0, -50.0, model, proj, viewport, &winx, &winy, &winz);
  280.     PSlineto(winx,winy);
  281.     gluProject(50.0, 0, 50.0, model, proj, viewport, &winx, &winy, &winz);
  282.     PSlineto(winx,winy);
  283.     gluProject(-50.0, 0, 50.0, model, proj, viewport, &winx, &winy, &winz);
  284.     PSlineto(winx,winy);
  285.     PSclosepath();
  286.     PSstroke();
  287.  
  288.     /* draw the "north" arrow */
  289.     PSnewpath();
  290.     gluProject(-10.0, 0, 0.0, model, proj, viewport, &winx, &winy, &winz);
  291.     PSmoveto(winx,winy);
  292.     gluProject(10.0, 0, 0.0, model, proj, viewport, &winx, &winy, &winz);
  293.     PSlineto(winx,winy);
  294.     gluProject(0.0, 0, 10.0, model, proj, viewport, &winx, &winy, &winz);
  295.     PSmoveto(winx,winy);
  296.     gluProject(0.0, 0, -15.0, model, proj, viewport, &winx, &winy, &winz);
  297.     PSlineto(winx,winy);
  298.     gluProject(-5.0, 0, -10.0, model, proj, viewport, &winx, &winy, &winz);
  299.     PSmoveto(winx,winy);
  300.     gluProject(0.0, 0, -15.0, model, proj, viewport, &winx, &winy, &winz);
  301.     PSlineto(winx,winy);
  302.     gluProject(5.0, 0, -10.0, model, proj, viewport, &winx, &winy, &winz);
  303.     PSlineto(winx,winy);
  304.     PSstroke();
  305. }
  306.