terrain.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:13k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /*
  2.  * This program is under the GNU GPL.
  3.  * Use at your own risk.
  4.  *
  5.  * written by David Bucciarelli (tech.hmw@plus.it)
  6.  *            Humanware s.r.l.
  7.  *
  8.  * based on a Mikael SkiZoWalker's (MoDEL) / France (Skizo@Hol.Fr) demo
  9.  */
  10. #include <stdio.h>
  11. #include <math.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <time.h>
  15. #ifdef _WIN32
  16. #include <windows.h>
  17. #endif
  18. #include <GL/glut.h>
  19. #ifndef M_PI
  20. #define M_PI 3.14159265
  21. #endif
  22. #define heightMnt 450
  23. #define lenghtXmnt 62
  24. #define lenghtYmnt 62
  25. #define stepXmnt     96.0
  26. #define stepYmnt     96.0
  27. #define WIDTH 640
  28. #define HEIGHT 480
  29. #define TSCALE 4
  30. #define FRAME 50
  31. #define FOV 85
  32. static GLfloat terrain[256*256];
  33. static GLfloat terraincolor[256*256][3];
  34. static int fog=1;
  35. static int bfcull=1;
  36. static int usetex=1;
  37. static int poutline=0;
  38. static int help=1;
  39. static int joyavailable=0;
  40. static int joyactive=0;
  41. static long GlobalMnt=0;
  42. static int scrwidth=WIDTH;
  43. static int scrheight=HEIGHT;
  44. #define OBSSTARTX 992.0
  45. #define OBSSTARTY 103.0
  46. static float obs[3]={OBSSTARTX,heightMnt*1.3,OBSSTARTY};
  47. static float dir[3],v1[2],v2[2];
  48. static float v=0.0;
  49. static float alpha=75.0;
  50. static float beta=90.0;
  51. static float gettime(void)
  52. {
  53.   static clock_t told=0;
  54.   clock_t tnew,ris;
  55.   tnew=clock();
  56.   ris=tnew-told;
  57.   told=tnew;
  58.   return(ris/(float)CLOCKS_PER_SEC);
  59. }
  60. static void calcposobs(void)
  61. {
  62.   float alpha1,alpha2;
  63.   dir[0]=sin(alpha*M_PI/180.0);
  64.   dir[2]=cos(alpha*M_PI/180.0)*sin(beta*M_PI/180.0);
  65.   dir[1]=cos(beta*M_PI/180.0);
  66.   alpha1=alpha+FOV/2.0;
  67.   v1[0]=sin(alpha1*M_PI/180.0);
  68.   v1[1]=cos(alpha1*M_PI/180.0);
  69.   alpha2=alpha-FOV/2.0;
  70.   v2[0]=sin(alpha2*M_PI/180.0);
  71.   v2[1]=cos(alpha2*M_PI/180.0);
  72.   
  73.   obs[0]+=v*dir[0];
  74.   obs[1]+=v*dir[1];
  75.   obs[2]+=v*dir[2];
  76.   if(obs[1]<0.0)
  77.     obs[1]=0.0;
  78. }
  79. static void reshape( int width, int height )
  80. {
  81.   scrwidth=width;
  82.   scrheight=height;
  83.   glViewport(0, 0, (GLint)width, (GLint)height);
  84.   glMatrixMode(GL_PROJECTION);
  85.   glLoadIdentity();
  86.   gluPerspective(50.0, ((GLfloat) width/(GLfloat)height), lenghtXmnt*stepYmnt*0.01,
  87.  lenghtXmnt*stepYmnt*0.7);
  88.   glMatrixMode(GL_MODELVIEW);
  89.   glLoadIdentity();
  90. }
  91. int clipstrip(float y, float *start, float *end)
  92. {
  93.   float x1,x2,t1,t2,tmp;
  94.   if(v1[1]==0.0) {
  95.     t1=0.0;
  96.     x1=-HUGE_VAL;
  97.   } else {
  98.     t1=y/v1[1];
  99.     x1=t1*v1[0];
  100.   }
  101.   if(v2[1]==0.0) {
  102.     t2=0.0;
  103.     x2=HUGE_VAL;
  104.   } else {
  105.     t2=y/v2[1];
  106.     x2=t2*v2[0];
  107.   }
  108.   if(((x1<-(lenghtXmnt*stepXmnt)/2) && (t2<=0.0)) ||
  109.      ((t1<=0.0) && (x2>(lenghtXmnt*stepXmnt)/2)) ||
  110.      ((t1<0.0) && (t2<0.0)))
  111.     return 0;
  112.   if((t1==0.0) && (t2==0.0)) {
  113.     if((v1[0]<0.0) && (v1[1]>0.0) && (v2[0]<0.0) && (v2[1]<0.0)) {
  114.       *start=-(lenghtXmnt*stepXmnt)/2;
  115.       *end=stepXmnt;
  116.       return 1;
  117.     } else {
  118.       if((v1[0]>0.0) && (v1[1]<0.0) && (v2[0]>0.0) && (v2[1]>0.0)) {
  119. *start=-stepXmnt;
  120. *end=(lenghtXmnt*stepXmnt)/2;
  121. return 1;
  122.       } else
  123. return 0;
  124.     }
  125.   } else {
  126.     if(t2<0.0) {
  127.       if(x1<0.0)
  128. x2=-(lenghtXmnt*stepXmnt)/2;
  129.       else
  130. x2=(lenghtXmnt*stepXmnt)/2;
  131.     }
  132.     if(t1<0.0) {
  133.       if(x2<0.0)
  134. x1=-(lenghtXmnt*stepXmnt)/2;
  135.       else
  136. x1=(lenghtXmnt*stepXmnt)/2;
  137.     }
  138.   }
  139.   if(x1>x2) {
  140.     tmp=x1;
  141.     x1=x2;
  142.     x2=tmp;
  143.   }
  144.   x1-=stepXmnt;
  145.   if(x1<-(lenghtXmnt*stepXmnt)/2)
  146.     x1=-(lenghtXmnt*stepXmnt)/2;
  147.   x2+=stepXmnt;
  148.   if(x2>(lenghtXmnt*stepXmnt)/2)
  149.     x2=(lenghtXmnt*stepXmnt)/2;
  150.   *start=((int)(x1/stepXmnt))*stepXmnt;
  151.   *end=((int)(x2/stepXmnt))*stepXmnt;
  152.   return 1;
  153. }
  154. static void printstring(void *font, char *string)
  155. {
  156.   int len,i;
  157.   len=(int)strlen(string);
  158.   for(i=0;i<len;i++)
  159.     glutBitmapCharacter(font,string[i]);
  160. }
  161. static void printhelp(void)
  162. {
  163.   glEnable(GL_BLEND);
  164.   glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  165.   glColor4f(0.0,0.0,0.0,0.5);
  166.   glRecti(40,40,600,440);
  167.   glDisable(GL_BLEND);
  168.   glColor3f(1.0,0.0,0.0);
  169.   glRasterPos2i(300,420);
  170.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Help");
  171.   glRasterPos2i(60,390);
  172.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"h - Togle Help");
  173.   glRasterPos2i(60,360);
  174.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"t - Togle Textures");
  175.   glRasterPos2i(60,330);
  176.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"f - Togle Fog");
  177.   glRasterPos2i(60,300);
  178.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"p - Wire frame");
  179.   glRasterPos2i(60,270);
  180.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"b - Togle Back face culling");
  181.   glRasterPos2i(60,240);
  182.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Arrow Keys - Rotate");
  183.   glRasterPos2i(60,210);
  184.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"a - Increase velocity");
  185.   glRasterPos2i(60,180);
  186.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"z - Decrease velocity");
  187.   glRasterPos2i(60,150);
  188.   if(joyavailable)
  189.     printstring(GLUT_BITMAP_TIMES_ROMAN_24,"j - Togle jostick control (Joystick control available)");
  190.   else
  191.     printstring(GLUT_BITMAP_TIMES_ROMAN_24,"(No Joystick control available)");
  192. }
  193. void drawterrain(void)
  194. {
  195.   int h,i,idx,ox,oy;
  196.   float j,k,start,end;
  197.   ox=(int)(obs[0]/stepXmnt);
  198.   oy=(int)(obs[2]/stepYmnt);
  199.   GlobalMnt=((ox*TSCALE)&255)+((oy*TSCALE)&255)*256;
  200.   glPushMatrix();
  201.   glTranslatef((float)ox*stepXmnt,0,(float)oy*stepYmnt);
  202.   for(h=0,k=-(lenghtYmnt*stepYmnt)/2;h<lenghtYmnt;k+=stepYmnt,h++) {
  203.     if(!clipstrip(k,&start,&end))
  204.       continue;
  205.     glBegin(GL_TRIANGLE_STRIP); /* I hope that the optimizer will be able to improve this code */
  206.     for(i=(int)(lenghtXmnt/2+start/stepXmnt),j=start;j<=end;j+=stepXmnt,i++) {
  207.       idx=(i*TSCALE+h*256*TSCALE+GlobalMnt)&65535;
  208.       glColor3fv(terraincolor[idx]);
  209.       glTexCoord2f((ox+i)/8.0,(oy+h)/8.0);
  210.       glVertex3f(j,terrain[idx],k);
  211.       idx=(i*TSCALE+h*256*TSCALE+256*TSCALE+GlobalMnt)&65535; 
  212.       glColor3fv(terraincolor[idx]);
  213.       glTexCoord2f((ox+i)/8.0,(oy+h+1)/8.0);
  214.       glVertex3f(j,terrain[idx],k+stepYmnt);
  215.     }
  216.     glEnd();
  217.   }
  218.   glDisable(GL_CULL_FACE);
  219.   glDisable(GL_TEXTURE_2D);
  220.   glEnable(GL_BLEND);
  221.   glBegin(GL_QUADS);
  222.   glColor4f(0.1,0.7,1.0,0.4);
  223.   glVertex3f(-(lenghtXmnt*stepXmnt)/2.0,heightMnt*0.6,-(lenghtYmnt*stepYmnt)/2.0);
  224.   glVertex3f(-(lenghtXmnt*stepXmnt)/2.0,heightMnt*0.6,(lenghtYmnt*stepYmnt)/2.0);
  225.   glVertex3f((lenghtXmnt*stepXmnt)/2.0,heightMnt*0.6,(lenghtYmnt*stepYmnt)/2.0);
  226.   glVertex3f((lenghtXmnt*stepXmnt)/2.0,heightMnt*0.6,-(lenghtYmnt*stepYmnt)/2.0);
  227.   glEnd();
  228.   glDisable(GL_BLEND);
  229.   if(bfcull)
  230.     glEnable(GL_CULL_FACE);
  231.   glEnable(GL_TEXTURE_2D);
  232.   glPopMatrix();
  233. }
  234. static void dojoy(void)
  235. {
  236. #ifdef _WIN32
  237.   static UINT max[2]={0,0};
  238.   static UINT min[2]={0xffffffff,0xffffffff},center[2];
  239.   MMRESULT res;
  240.   JOYINFO joy;
  241.   res=joyGetPos(JOYSTICKID1,&joy);
  242.   if(res==JOYERR_NOERROR) {
  243.     joyavailable=1;
  244.     if(max[0]<joy.wXpos)
  245.       max[0]=joy.wXpos;
  246.     if(min[0]>joy.wXpos)
  247.       min[0]=joy.wXpos;
  248.     center[0]=(max[0]+min[0])/2;
  249.     if(max[1]<joy.wYpos)
  250.       max[1]=joy.wYpos;
  251.     if(min[1]>joy.wYpos)
  252.       min[1]=joy.wYpos;
  253.     center[1]=(max[1]+min[1])/2;
  254.     if(joyactive) {
  255.       if(fabs(center[0]-(float)joy.wXpos)>0.1*(max[0]-min[0]))
  256. alpha+=2.5*(center[0]-(float)joy.wXpos)/(max[0]-min[0]);
  257.       if(fabs(center[1]-(float)joy.wYpos)>0.1*(max[1]-min[1]))
  258. beta+=2.5*(center[1]-(float)joy.wYpos)/(max[1]-min[1]);
  259.       if(joy.wButtons & JOY_BUTTON1)
  260. v+=0.5;
  261.       if(joy.wButtons & JOY_BUTTON2)
  262. v-=0.5;
  263.     }
  264.   } else
  265.     joyavailable=0;
  266. #endif
  267. }
  268. void drawscene(void)
  269. {
  270.   static int count=0;
  271.   static char frbuf[80];
  272.   float fr;
  273.   dojoy();
  274.   glShadeModel(GL_SMOOTH);
  275.   glEnable(GL_DEPTH_TEST);
  276.   if(usetex)
  277.     glEnable(GL_TEXTURE_2D);
  278.   else
  279.     glDisable(GL_TEXTURE_2D);
  280.   if(fog)
  281.     glEnable(GL_FOG);
  282.   else
  283.     glDisable(GL_FOG);
  284.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  285.   glPushMatrix();
  286.   calcposobs();
  287.   gluLookAt(obs[0],obs[1],obs[2],
  288.     obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2],
  289.     0.0,1.0,0.0);
  290.   drawterrain();
  291.   glPopMatrix();
  292.   if((count % FRAME)==0) {
  293.     fr=gettime();
  294.     sprintf(frbuf,"Frame rate: %.3f",FRAME/fr);
  295.   }
  296.   glDisable(GL_TEXTURE_2D);
  297.   glDisable(GL_DEPTH_TEST);
  298.   glDisable(GL_FOG);
  299.   glShadeModel(GL_FLAT);
  300.   glMatrixMode(GL_PROJECTION);
  301.   glLoadIdentity();
  302.   glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
  303.   glMatrixMode(GL_MODELVIEW);
  304.   glLoadIdentity();
  305.   glColor3f(1.0,0.0,0.0);
  306.   glRasterPos2i(10,10);
  307.   printstring(GLUT_BITMAP_HELVETICA_18,frbuf);
  308.   glRasterPos2i(350,470);
  309.   printstring(GLUT_BITMAP_HELVETICA_10,"Terrain V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
  310.   glRasterPos2i(434,457);
  311.   printstring(GLUT_BITMAP_HELVETICA_10,"Based on a Mickael's demo (Skizo@Hol.Fr)");
  312.   if(help)
  313.     printhelp();
  314.   reshape(scrwidth,scrheight);
  315.   glutSwapBuffers();
  316.   count++;
  317. }
  318. /* ARGSUSED1 */
  319. static void key(unsigned char k, int x, int y)
  320. {
  321.   switch (k) {
  322.   case 27:
  323.     exit(0);
  324.     break;
  325.   case 'a':
  326.     v+=0.5;
  327.     break;
  328.   case 'z':
  329.     v-=0.5;
  330.     break;
  331.   case 'p':
  332.     if(poutline) {
  333.       glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
  334.       poutline=0;
  335.     } else {
  336.       glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
  337.       poutline=1;
  338.     }
  339.     break;
  340.   case 'j':
  341.     joyactive=(!joyactive);
  342.     break;
  343.   case 'h':
  344.     help=(!help);
  345.     break;
  346.   case 'f':
  347.     fog=(!fog);
  348.     break;
  349.   case 't':
  350.     usetex=(!usetex);
  351.     break;
  352.   case 'b':
  353.     if(bfcull) {
  354.       glDisable(GL_CULL_FACE);
  355.       bfcull=0;
  356.     } else {
  357.       glEnable(GL_CULL_FACE);
  358.       bfcull=1;
  359.     }
  360.     break;
  361.   }
  362. }
  363. /* ARGSUSED1 */
  364. static void special(int k, int x, int y)
  365. {
  366.   switch(k) {
  367.   case GLUT_KEY_LEFT:
  368.     alpha+=2.0;
  369.     break;
  370.   case GLUT_KEY_RIGHT:
  371.     alpha-=2.0;
  372.     break;
  373.   case GLUT_KEY_DOWN:
  374.     beta-=2.0;
  375.     break;
  376.   case GLUT_KEY_UP:
  377.     beta+=2.0;
  378.     break;
  379.   }
  380. }
  381. static void calccolor(GLfloat height, GLfloat c[3])
  382. {
  383.   GLfloat color[4][3]={
  384.     {1.0,1.0,1.0},
  385.     {0.0,0.8,0.0},
  386.     {1.0,1.0,0.3},
  387.     {0.0,0.0,0.8}
  388.   };
  389.   GLfloat fact;
  390.   height=height*(1.0/255.0);
  391.   if(height>=0.9) {
  392.     c[0]=color[0][0]; c[1]=color[0][1]; c[2]=color[0][2];
  393.     return;
  394.   }
  395.   if((height<0.9) && (height>=0.7)) {
  396.     fact=(height-0.7)*5.0;
  397.     c[0]=fact*color[0][0]+(1.0-fact)*color[1][0];
  398.     c[1]=fact*color[0][1]+(1.0-fact)*color[1][1];
  399.     c[2]=fact*color[0][2]+(1.0-fact)*color[1][2];
  400.     return;
  401.   }
  402.   if((height<0.7) && (height>=0.6)) {
  403.     fact=(height-0.6)*10.0;
  404.     c[0]=fact*color[1][0]+(1.0-fact)*color[2][0];
  405.     c[1]=fact*color[1][1]+(1.0-fact)*color[2][1];
  406.     c[2]=fact*color[1][2]+(1.0-fact)*color[2][2];
  407.     return;
  408.   }
  409.   if((height<0.6) && (height>=0.5)) {
  410.     fact=(height-0.5)*10.0;
  411.     c[0]=fact*color[2][0]+(1.0-fact)*color[3][0];
  412.     c[1]=fact*color[2][1]+(1.0-fact)*color[3][1];
  413.     c[2]=fact*color[2][2]+(1.0-fact)*color[3][2];
  414.     return;
  415.   }
  416.   c[0]=color[3][0]; c[1]=color[3][1]; c[2]=color[3][2];
  417. }
  418. static void loadpic (void)
  419. {
  420.   GLubyte bufferter[256*256],terrainpic[256*256];
  421.   FILE *FilePic;
  422.   int i,tmp;
  423.   GLenum gluerr;
  424.   if((FilePic=fopen("mnt.bin","r"))==NULL) {
  425.     fprintf(stderr,"Error loading Mnt.binn");
  426.     exit(-1);
  427.   }
  428.   fread(bufferter , 256*256 , 1 , FilePic);
  429.   fclose(FilePic);
  430.   for (i=0;i<(256*256);i++) {
  431.     terrain[i]=(bufferter[i]*(heightMnt/255.0f));
  432.     calccolor((GLfloat)bufferter[i],terraincolor[i]);
  433.     tmp=(((int)bufferter[i])+96);
  434.     terrainpic[i]=(tmp>255) ? 255 : tmp;
  435.   }
  436.   glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  437.   if((gluerr=gluBuild2DMipmaps(GL_TEXTURE_2D, 1, 256, 256, GL_LUMINANCE,
  438.        GL_UNSIGNED_BYTE, (GLvoid *)(&terrainpic[0])))) {
  439.     fprintf(stderr,"GLULib%sn",gluErrorString(gluerr));
  440.     exit(-1);
  441.   }
  442.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
  443.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
  444.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_LINEAR);
  445.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  446.   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
  447.   glEnable(GL_TEXTURE_2D);
  448. }
  449. static void init( void )
  450. {
  451.   float fogcolor[4]={0.6,0.7,0.7,1.0};
  452.   glClearColor(fogcolor[0],fogcolor[1],fogcolor[2],fogcolor[3]);
  453.   glClearDepth(1.0);
  454.   glDepthFunc(GL_LEQUAL);
  455.   glShadeModel(GL_SMOOTH);
  456.   glEnable(GL_DEPTH_TEST);
  457.   glEnable(GL_CULL_FACE);
  458.   glDisable(GL_BLEND);
  459.   glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  460.   glEnable(GL_FOG);
  461.   glFogi(GL_FOG_MODE,GL_EXP2);
  462.   glFogfv(GL_FOG_COLOR,fogcolor);
  463.   glFogf(GL_FOG_DENSITY,0.0007);
  464. #ifdef FX
  465.   glHint(GL_FOG_HINT,GL_NICEST);
  466. #endif
  467.   reshape(scrwidth,scrheight);
  468. }
  469. int main(int ac, char **av)
  470. {
  471.   glutInitWindowPosition(0,0);
  472.   glutInitWindowSize(WIDTH,HEIGHT);
  473.   glutInit(&ac,av);
  474.   glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
  475.   glutCreateWindow("Terrain");
  476.   loadpic();
  477.   init();
  478. #ifndef FX
  479.   glDisable(GL_TEXTURE_2D);
  480.   usetex=0;
  481. #endif
  482.   glutReshapeFunc(reshape);
  483.   glutDisplayFunc(drawscene);
  484.   glutKeyboardFunc(key);
  485.   glutSpecialFunc(special);
  486.   glutIdleFunc(drawscene);
  487.   glutMainLoop();
  488.   return 0;             /* ANSI C requires main to return int. */
  489. }