head	1.1;
access;
symbols;
locks; strict;
comment	@ * @;


1.1
date	99.06.08.00.56.10;	author brianp;	state Exp;
branches;
next	;


desc
@@


1.1
log
@initial check-in
@
text
@#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "mesadraw.h"
#include "vect3d.h"

#define DIM 32
#define MAX_HEIGHT (300/DIM)
#define RADS(x) ((x)/57.29577951)

static GLdouble mesh[DIM][DIM][3];
static GLubyte cols[DIM][DIM][3];

/*
 * Create a random matrix of heights and colours
 */

void make_matrix(void)
{
  int i,j;

  for(i=0;i<DIM;i++)
    for(j=0;j<DIM;j++)
     {
       mesh[i][j][0]=((100.0*i)/(DIM-1.0))-50.0;
       mesh[i][j][2]=((100.0*j)/(DIM-1.0))-50.0;
       mesh[i][j][1]=(rand()%MAX_HEIGHT);
       cols[i][j][0]=(mesh[i][j][1]*255)/MAX_HEIGHT;
       cols[i][j][1]=255-cols[i][j][0];
       cols[i][j][2]=0;
     }
}

/*
 * Initialise the OpenGL stuff
 */

void my_init (float w, float h) 
{
  GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
  GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
  GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  GLfloat light_position[] = { 5.0, 3.0, 9.0, 0.0 };

  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  glMatrixMode (GL_MODELVIEW);
  glLoadIdentity ();


  glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
  glLightfv(GL_LIGHT0, GL_POSITION, light_position);

  glShadeModel(GL_SMOOTH);
  glEnable(GL_LIGHT0);
  glEnable(GL_LIGHTING);
  glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
  glEnable(GL_COLOR_MATERIAL);
  glEnable(GL_DEPTH_TEST);

  glViewport(0,0,w,h);
  glMatrixMode (GL_PROJECTION);
  gluPerspective (60.0, w/h, 1.0, 400.0);
}

/*
 * Set the viewpoint
 */

void set_viewpoint(float zoomDist, float elevAngle, float spinAngle)
{
    float flat_radius, x, y, z, xl, zl;
    flat_radius=zoomDist*cos(RADS(elevAngle));
    x=0.0-(flat_radius*sin(RADS(spinAngle)));
    xl=50.0*sin(RADS(spinAngle));
    z=flat_radius*cos(RADS(spinAngle));
    zl= -50.0*cos(RADS(spinAngle));
    y=zoomDist*sin(RADS(elevAngle));

    glMatrixMode (GL_MODELVIEW);
    glLoadIdentity ();
/*
 * we make a somewhat spurious "up" vector because we know we are 
 * looking at the origin and that it's mapped into the plane of
 * the screen anyway so the percise direction is irrelevent.
 */
    gluLookAt (x, y, z,
               0, 0, 0,
               xl, 50, zl);
}

/*
 * Get a normal to a corner of a quad.
 */

void get_quad_normal(int x, int z, int cx, int cz, GLdouble n[3])
{
        GLdouble *c1, *c2, *c3, *c4;
        c1 = &mesh[x][z][0];
        c2 = &mesh[x+1][z][0];
        c3 = &mesh[x+1][z+1][0];
        c4 = &mesh[x][z+1][0];
        if((cx==0) && (cz==0))
         return perpnorm(c4,c1,c2,n);
        if((cx==0) && (cz==0))
         return perpnorm(c4,c1,c2,n);
        if((cx==1) && (cz==0))
          return perpnorm(c1,c2,c3,n);
        if((cx==1) && (cz==1))
          return perpnorm(c2,c3,c4,n);
        if((cx==0) && (cz==1))
          return perpnorm(c3,c4,c1,n);
}

/*
 * Get a normal to a plane as the average of
 * the normals at the four corners of the quad.
 */

void get_plane_normal(int x, int z, GLdouble n[3])
{
   GLdouble total[3]={0,0,0};
   get_quad_normal(x,z,0,0,n);
   add3(total,n,total);
   get_quad_normal(x,z,0,1,n);
   add3(total,n,total);
   get_quad_normal(x,z,1,0,n);
   add3(total,n,total);
   get_quad_normal(x,z,1,1,n);
   add3(total,n,total);
   normalize(total);
   n[0]=total[0];
   n[1]=total[1];
   n[2]=total[2];
}

/*
 * Get a normal to a point as the average
 * of the surrounding quads.
 */

void get_vertex_normal(int x, int z, GLdouble n[3])
{
   GLdouble total[3]={0,0,0};
   if((x>0) && (z>0))
    {
     get_quad_normal(x-1,z-1,1,1,n);
     add3(total,n,total);
    }
   if((x>0) && (z<(DIM-1)))
    {
     get_quad_normal(x-1,z,1,0,n);
     add3(total,n,total);
    }
   if((x<(DIM-1)) && (z>0))
    {
     get_quad_normal(x,z-1,0,1,n);
     add3(total,n,total);
    }
   if((x<(DIM-1)) && (z<(DIM-1)))
    {
     get_quad_normal(x,z,0,0,n);
     add3(total,n,total);
    }
   normalize(total);
   n[0]=total[0];
   n[1]=total[1];
   n[2]=total[2];
}

/*
 * Draw the scene
 */

void draw_scene(int av, int drape, int white)
{
    int xstrip, zrow;

    if(drape) {
        glTexImage2D(GL_TEXTURE_2D, 0, 3,
                     DIM, DIM, 0, GL_RGB,
                     GL_UNSIGNED_BYTE, &cols[0][0][0]);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glEnable(GL_TEXTURE_2D);
    }
    else
        glDisable(GL_TEXTURE_2D);

    /*
     * Clear the image buffer.
     */
    if(white)
     glClearColor(1,1,1,1);
    else
     glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    if(drape)
        glColor3ub(255,255,255);    /* basic white surface to be modulated */
    for(xstrip=0;xstrip<DIM-1;xstrip++)
     {
      glBegin(GL_QUADS);
      for(zrow=0;zrow<DIM-1;zrow++)
       {
        GLdouble *c1, *c2, *c3, *c4;
        GLdouble n1[3], n2[3], n3[3], n4[3];
        GLdouble t1[2], t2[2], t3[2], t4[2];
        int passes,toggle;

        /* corner co-ords */
        c1 = &mesh[xstrip][zrow][0];
        c2 = &mesh[xstrip+1][zrow][0];
        c3 = &mesh[xstrip+1][zrow+1][0];
        c4 = &mesh[xstrip][zrow+1][0];

        /*
         * texture co-ords - these look a bit odd, but we don't want to
         * drape the entire texture over the surface - the vertices are
         * assumed to be the centres of the squares on the texture and thus
         * vertex 0,0 is halfway into the first square of the texture. Thus
         * the texture is DIM wide, but the surface is DIM-1 wide compared
         * to it - hence the +0.5's to offset the surface into the texture.
         */
        t1[1]=(xstrip+0.5)/DIM;	t1[0]=(zrow+0.5)/DIM;
        t2[1]=(xstrip+1.5)/DIM;	t2[0]=(zrow+0.5)/DIM;
        t3[1]=(xstrip+1.5)/DIM;	t3[0]=(zrow+1.5)/DIM;
        t4[1]=(xstrip+0.5)/DIM;	t4[0]=(zrow+1.5)/DIM;

        /* normal vectors */
        if(av)
         {
          get_vertex_normal(xstrip,zrow,n1);
          get_vertex_normal(xstrip+1,zrow,n2);
          get_vertex_normal(xstrip+1,zrow+1,n3);
          get_vertex_normal(xstrip,zrow+1,n4);
         }
        else
         {
          get_plane_normal(xstrip,zrow,n1);
          memcpy(n2,n1,3*sizeof(GLdouble));
          memcpy(n3,n1,3*sizeof(GLdouble));
          memcpy(n4,n1,3*sizeof(GLdouble));
         }

        /*
         * we do this to draw the quads in the opposite direction for
         * each strip as this reduces the effects of the triangluarisation
         * of the quad by the rendering algorithm.
         */
        for(passes=0;passes<4;passes++)
         {
         if((xstrip&1) == (zrow&1))
          toggle=3-passes;
         else
          toggle=passes;
         switch (toggle)
          {
          case 0:
           glNormal3dv(n1);
           if(drape)
               glTexCoord2dv(t1);
           else
               glColor3ubv(&cols[xstrip][zrow][0]);
           glVertex3dv(c1);
           break;

          case 1:
           glNormal3dv(n2);
           if(drape)
               glTexCoord2dv(t2);
           else
               glColor3ubv(&cols[xstrip+1][zrow][0]);
           glVertex3dv(c2);
           break;

          case 2:
           glNormal3dv(n3);
           if(drape)
               glTexCoord2dv(t3);
           else
               glColor3ubv(&cols[xstrip+1][zrow+1][0]);
           glVertex3dv(c3);
           break;
   
          case 3:
           glNormal3dv(n4);
           if(drape)
               glTexCoord2dv(t4);
           else
               glColor3ubv(&cols[xstrip][zrow+1][0]);
           glVertex3dv(c4);
           break;
          }
         }
       }
      glEnd();
     }

    glFlush();
}

/*
 * We use the display postscript operators to senÚ»Ï+M¼“Sgî�™¤ŠðÁíhxyÑ¡šìt<ÿ'ÁHR×ÎòoÃß™æ¢ŒcO´¦;^Ü,”K¬ÄôGð¯ž0mø‘õÃ„–¦Ó�<Y%!š„'!š‰í“¡W"Ú~ÕÚ»ŸkltLü µj²±"·PºÓèœ:Þÿ»ÞÐÂæl—Í	óë¸º¿_I>•¯FÜóFMjÛ{‰GŒ½®Vœü«³-Œƒ›ž�vpý-éƒáCSÍDÑ£Ð+º Ø©îÄÇn]£ë[Ï’üDëD8ä.u´Òò¿ççd¸pþj¤µ°T¸x$÷Ùòqï”ë”…$=”o®=AàUÖcûIÂsM$ßÈ>ÖieîL¿þŠñ'?õYÏvm,¬÷Ú‚ q¥[YO>>qÈQH²Çß³Œ=Ã‡]kï-Ý9JÐê{°7<a:þxq-†ã††Nm�	mY®½J¢Ÿ×“¯Þa>�XN¶æßí]�«™±Y{Õa�7fá-|Ï¦^qþæ�&[?j©äÜÅÕÎœ­åTŸ}†�ñçB)äÅ.ž(°Œ�ä×ÅPô¹¡6S›•³w¦k×3Q2ñïx¾Ïq¢Ðh¤™uüÇòéèúš}š1’<”�¤ŽZ-¬¦Œ“]`¼«…;9ã�ó,Ý[<çþ›’O0\ïxèL,^TM§9}xNTÄcçÑNióWLis<"€–¡E9³kPOÖÑœà„‡6�kÖ“=#Ib>OÞZà‹IíÑ95…7gòÜVshÔ=b�lÙ Võ2nÌbxD¸c3ã�þ¡ùýþ¡q<O×æœ²'øXõó¶™roqÈTâØ!­746÷9X$øžüG`Mu_@ùå>ªSøÒ–ž|—KýiË±ëã¯#¶a°žmÿ‹ÏÁ‚V³OÖ¥A¤y”‚#îÒ<ø×»Èƒ«ëwð>¿¥�Â’ý¹mÔäE3¸¡­f|v„Úû'þÊõ©q|Ÿ ,U¸µ™›µg¼ÇKYËêeÞ41¨W¬>8ðµcýø™˜Zîïk’¡�i¹ò²³on½ôm·G@zˆ?À†àh‘u8øiÉÖÉ¹Rp�qÈyÁ"ø]�HL½Í’hç®w‰«ÿ£Ž0ÜPÔl¹± ðV´k^=¸O_8xî7züµo%³YL5wVåGn¤tô^Çéý÷n€Ô”@÷êhÕy<2”iyj]½¶è]Õ<íš=‰8âÎ¾UòH„µˆ–�ŒuùÞÚ�!XôT�~Bþ`ë•+ûBhÙ­øäª,É§G§øƒ5eŸÆkêâg+¨ÿ$h?–C)°¥�—l|ø øi¿O‹ïk°)~6_ããor·ÀG P‘kTÝxkýïôÌò"‘½Ö¤¬i;Ÿg8Ðª:º„Zä¶>ûøG.‚7²dÓ›SS¡Fîw í“‡FEITEOnn"+_)œœÍ-÷0é�¢{Öj6Øü��¨øûGç�ï«ÐÁ�ppûÕº$RÅï+ŠUv{ŸßÌÇÂM*ï7z¾N |:Òœ¬éîŸÓ“wé,3>½8QSïÜïYAÝ¯\æ½Ýr?DrÁ	0oYÔY‡rîÿ,î<HW„EŒà™ŸõŠ+îß¬’g‘5Ã5Á[oþ™•G!×c‹<ïó	<AD´;»f™ùDx,ñy�Ð«tÜÄüTq¼jíôÊ‰ï[åNýXöÝ�Â\Ê§wÉJµ"Øèœ¤;xèZú»0Wo=�U�è²O«ìþÄ–nLt»4þßzÈò­b²Áê#°ÁØŽ€Æv$-†5	Ú‚¹Ü£…[ö<ôX<,FìŠ<º·BXhq«ñlM?WA™Ltz4¾
ÞªqUS†LŒ‡¥–ÎïsBßöèO‘C6¿}“6·‘óŸ”®w¿ËòŸé%ëeJøçª­C^ìüØ“Ô®ˆbå¨ŒÝ’SYM9Dpô¶ê­Ýè˜A¢X:˜÷óy”¢:™—„Ø4£Ö±äã¿ì`§1yüàâiÝÑo´1Öì_ï*¡ë'f>:¨ÿùÇ÷ÆJ_Æ-ÅðuÛ}ä,ÔvÇ¼å¶ÆÛA±që¤ÆkE�›2øk\3"ú×&ùŸÄúšeÇÉ½çÎQ y™Ý�ÃúŒBè¾Ì¡–�ØNšñ÷Þh�¨ÛÚ{E¸Q4×Ô¼Ÿm~S¡¶µ{¾³¸­·m"ß$û