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

GIS编程

开发平台:

Visual C++

  1. /* sphere.c - by David Blythe, SGI */
  2. /* Instead of tessellating a sphere by lines of longitude and latitude
  3.    (a technique that over tessellates the poles and under tessellates
  4.    the equator of the sphere), tesselate based on regular solids for a
  5.    more uniform tesselation.
  6.    This approach is arguably better than the gluSphere routine's
  7.    approach using slices and stacks (latitude and longitude). -mjk */
  8. #include <stdlib.h>
  9. #include <GL/glut.h>
  10. #include <math.h>
  11. typedef struct {
  12.     float x, y, z;
  13. } point;
  14. typedef struct {
  15.     point pt[3];
  16. } triangle;
  17. /* six equidistant points lying on the unit sphere */
  18. #define XPLUS {  1,  0,  0 }    /*  X */
  19. #define XMIN  { -1,  0,  0 }    /* -X */
  20. #define YPLUS {  0,  1,  0 }    /*  Y */
  21. #define YMIN  {  0, -1,  0 }    /* -Y */
  22. #define ZPLUS {  0,  0,  1 }    /*  Z */
  23. #define ZMIN  {  0,  0, -1 }    /* -Z */
  24. /* for icosahedron */
  25. #define CZ (0.89442719099991)   /*  2/sqrt(5) */
  26. #define SZ (0.44721359549995)   /*  1/sqrt(5) */
  27. #define C1 (0.951056516)        /* cos(18),  */
  28. #define S1 (0.309016994)        /* sin(18) */
  29. #define C2 (0.587785252)        /* cos(54),  */
  30. #define S2 (0.809016994)        /* sin(54) */
  31. #define X1 (C1*CZ)
  32. #define Y1 (S1*CZ)
  33. #define X2 (C2*CZ)
  34. #define Y2 (S2*CZ)
  35. #define Ip0     {0.,    0.,     1.}
  36. #define Ip1     {-X2,   -Y2,    SZ}
  37. #define Ip2     {X2,    -Y2,    SZ}
  38. #define Ip3     {X1,    Y1,     SZ}
  39. #define Ip4     {0,     CZ,     SZ}
  40. #define Ip5     {-X1,   Y1,     SZ}
  41. #define Im0     {-X1,   -Y1,    -SZ}
  42. #define Im1     {0,     -CZ,    -SZ}
  43. #define Im2     {X1,    -Y1,    -SZ}
  44. #define Im3     {X2,    Y2,     -SZ}
  45. #define Im4     {-X2,   Y2,     -SZ}
  46. #define Im5     {0.,    0.,     -1.}
  47. /* vertices of a unit icosahedron */
  48. static triangle icosahedron[20]= {
  49.         /* front pole */
  50.         { {Ip0, Ip1, Ip2}, },
  51.         { {Ip0, Ip5, Ip1}, },
  52.         { {Ip0, Ip4, Ip5}, },
  53.         { {Ip0, Ip3, Ip4}, },
  54.         { {Ip0, Ip2, Ip3}, },
  55.         /* mid */
  56.         { {Ip1, Im0, Im1}, },
  57.         { {Im0, Ip1, Ip5}, },
  58.         { {Ip5, Im4, Im0}, },
  59.         { {Im4, Ip5, Ip4}, },
  60.         { {Ip4, Im3, Im4}, },
  61.         { {Im3, Ip4, Ip3}, },
  62.         { {Ip3, Im2, Im3}, },
  63.         { {Im2, Ip3, Ip2}, },
  64.         { {Ip2, Im1, Im2}, },
  65.         { {Im1, Ip2, Ip1}, },
  66.         /* back pole */
  67.         { {Im3, Im2, Im5}, },
  68.         { {Im4, Im3, Im5}, },
  69.         { {Im0, Im4, Im5}, },
  70.         { {Im1, Im0, Im5}, },
  71.         { {Im2, Im1, Im5}, },
  72. };
  73. /* normalize point r */
  74. static void
  75. normalize(point *r) {
  76.     float mag;
  77.     mag = r->x * r->x + r->y * r->y + r->z * r->z;
  78.     if (mag != 0.0f) {
  79.         mag = 1.0f / sqrt(mag);
  80.         r->x *= mag;
  81.         r->y *= mag;
  82.         r->z *= mag;
  83.     }
  84. }
  85. /* linearly interpolate between a & b, by fraction f */
  86. static void
  87. lerp(point *a, point *b, float f, point *r) {
  88.     r->x = a->x + f*(b->x-a->x);
  89.     r->y = a->y + f*(b->y-a->y);
  90.     r->z = a->z + f*(b->z-a->z);
  91. }
  92. void
  93. sphere(int maxlevel) {
  94.     int nrows = 1 << maxlevel;
  95.     int s;
  96.     /* iterate over the 20 sides of the icosahedron */
  97.     for(s = 0; s < 20; s++) {
  98.         int i;
  99.         triangle *t = &icosahedron[s];
  100.         for(i = 0; i < nrows; i++) {
  101.             /* create a tstrip for each row */
  102.             /* number of triangles in this row is number in previous +2 */
  103.             /* strip the ith trapezoid block */
  104.             point v0, v1, v2, v3, va, vb;
  105.             int j;
  106.             lerp(&t->pt[1], &t->pt[0], (float)(i+1)/nrows, &v0);
  107.             lerp(&t->pt[1], &t->pt[0], (float)i/nrows, &v1);
  108.             lerp(&t->pt[1], &t->pt[2], (float)(i+1)/nrows, &v2);
  109.             lerp(&t->pt[1], &t->pt[2], (float)i/nrows, &v3);
  110.             glBegin(GL_TRIANGLE_STRIP);
  111. #define V(v)    { point x; x = v; normalize(&x); glNormal3fv(&x.x); glVertex3fv(&x.x); }
  112.             V(v0);
  113.             V(v1);
  114.             for(j = 0; j < i; j++) {
  115.                 /* calculate 2 more vertices at a time */
  116.                 lerp(&v0, &v2, (float)(j+1)/(i+1), &va);
  117.                 lerp(&v1, &v3, (float)(j+1)/i, &vb);
  118.                 V(va);
  119.                 V(vb);
  120.             }
  121.             V(v2);
  122. #undef V
  123.             glEnd();
  124.         }
  125.     }
  126. }
  127. float *
  128. sphere_tris(int maxlevel) {
  129.     int nrows = 1 << maxlevel;
  130.     int s, n;
  131.     float *buf, *b;
  132.     n = 20*(1 << (maxlevel * 2));
  133.     b = buf = (float *)malloc(n*3*3*sizeof(float));
  134.     /* iterate over the 20 sides of the icosahedron */
  135.     for(s = 0; s < 20; s++) {
  136.         int i;
  137.         triangle *t = &icosahedron[s];
  138.         for(i = 0; i < nrows; i++) {
  139.             /* create a tstrip for each row */
  140.             /* number of triangles in this row is number in previous +2 */
  141.             /* strip the ith trapezoid block */
  142.             point v0, v1, v2, v3, va, vb, x1, x2;
  143.             int j;
  144.             lerp(&t->pt[1], &t->pt[0], (float)(i+1)/nrows, &v0);
  145.             lerp(&t->pt[1], &t->pt[0], (float)i/nrows, &v1);
  146.             lerp(&t->pt[1], &t->pt[2], (float)(i+1)/nrows, &v2);
  147.             lerp(&t->pt[1], &t->pt[2], (float)i/nrows, &v3);
  148. #define V(a, c, v)      { point x = v; normalize(&a); normalize(&c); normalize(&x); 
  149.                         b[0] = a.x; b[1] = a.y; b[2] = a.z; 
  150.                         b[3] = c.x; b[4] = c.y; b[5] = c.z; 
  151.                         b[6] = x.x; b[7] = x.y; b[8] = x.z; b+=9; }
  152.             x1 = v0;
  153.             x2 = v1;
  154.             for(j = 0; j < i; j++) {
  155.                 /* calculate 2 more vertices at a time */
  156.                 lerp(&v0, &v2, (float)(j+1)/(i+1), &va);
  157.                 lerp(&v1, &v3, (float)(j+1)/i, &vb);
  158.                 V(x1,x2,va); x1 = x2; x2 = va;
  159.                 V(vb,x2,x1); x1 = x2; x2 = vb;
  160.             }
  161.             V(x1, x2, v2);
  162. #undef V
  163.         }
  164.     }
  165.     return buf;
  166. }