home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / MISC / D3DSPHR.C < prev    next >
C/C++ Source or Header  |  1996-08-28  |  8KB  |  212 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File: d3dsphr.c
  6.  *
  7.  ***************************************************************************/
  8.  
  9. #include <math.h>
  10. #include <d3d.h>
  11.  
  12. #define PI 3.1415
  13.  
  14. /*
  15.  * Generates a sphere around the y-axis centered at the origin including
  16.  * normals and texture coordiantes.  Returns TRUE on success and FALSE on
  17.  * failure.
  18.  *     sphere_r     Radius of the sphere.
  19.  *     num_rings    Number of full rings not including the top and bottom
  20.  *                  caps.
  21.  *     num_sections Number of sections each ring is divided into.  Each
  22.  *                  section contains two triangles on full rings and one 
  23.  *                  on top and bottom caps.
  24.  *     sx, sy, sz   Scaling along each axis.  Set each to 1.0 for a 
  25.  *                  perfect sphere. 
  26.  *     plpv         On exit points to the vertices of the sphere.  The
  27.  *                  function allocates this space.  Not allocated if
  28.  *                  function fails.
  29.  *     plptri       On exit points to the triangles of the sphere which 
  30.  *                  reference vertices in the vertex list.  The function
  31.  *                  allocates this space. Not allocated if function fails.
  32.  *     pnum_v       On exit contains the number of vertices.
  33.  *     pnum_tri     On exit contains the number of triangles.
  34.  */
  35. BOOL 
  36. GenerateSphere(float sphere_r, int num_rings, int num_sections, float sx, 
  37.                float sy, float sz, LPD3DVERTEX* plpv, 
  38.                LPD3DTRIANGLE* plptri, int* pnum_v, int* pnum_tri)
  39. {
  40.  
  41.     float theta, phi;    /* Angles used to sweep around sphere */
  42.     float dtheta, dphi;  /* Angle between each section and ring */
  43.     float x, y, z, v, rsintheta; /* Temporary variables */
  44.     int i, j, n, m;      /* counters */
  45.     int num_v, num_tri;  /* Internal vertex and triangle count */
  46.     LPD3DVERTEX lpv;     /* Internal pointer for vertices */
  47.     LPD3DTRIANGLE lptri; /* Internal pointer for trianlges */
  48.  
  49.     /*
  50.      * Check the parameters to make sure they are valid.
  51.      */
  52.     if ((sphere_r <= 0) || (num_rings < 1) || (num_sections < 3) ||
  53.         (sx <= 0) || (sy <= 0) || (sz <= 0))
  54.         return FALSE;
  55.     /*
  56.      * Generate space for the required triangles and vertices.
  57.      */
  58.     num_tri = (num_rings + 1) * num_sections * 2;
  59.     num_v = (num_rings + 1) * num_sections + 2;
  60.     *plpv = (LPD3DVERTEX) malloc(sizeof(D3DVERTEX) * num_v);
  61.     *plptri = (LPD3DTRIANGLE) malloc(sizeof(D3DTRIANGLE) * num_tri);
  62.     lpv = *plpv;
  63.     lptri = *plptri;
  64.     *pnum_v = num_v;
  65.     *pnum_tri = num_tri;
  66.  
  67.     /*
  68.      * Generate vertices at the top and bottom points.
  69.      */
  70.     lpv[0].x = D3DVAL(0.0);
  71.     lpv[0].y = D3DVAL(sy * sphere_r);
  72.     lpv[0].z = D3DVAL(0.0);
  73.     lpv[0].nx = D3DVAL(0.0);
  74.     lpv[0].ny = D3DVAL(1.0);
  75.     lpv[0].nz = D3DVAL(0.0);
  76.     lpv[0].tu = D3DVAL(0.0);
  77.     lpv[0].tv = D3DVAL(0.0);
  78.     lpv[num_v - 1].x = D3DVAL(0.0);
  79.     lpv[num_v - 1].y = D3DVAL(sy * -sphere_r);
  80.     lpv[num_v - 1].z = D3DVAL(0.0);
  81.     lpv[num_v - 1].nx = D3DVAL(0.0);
  82.     lpv[num_v - 1].ny = D3DVAL(-1.0);
  83.     lpv[num_v - 1].nz = D3DVAL(0.0);
  84.     lpv[num_v - 1].tu = D3DVAL(0.0);
  85.     lpv[num_v - 1].tv = D3DVAL(1.0);
  86.  
  87.  
  88.     /*
  89.      * Generate vertex points for rings
  90.      */
  91.     dtheta = (float)(PI / (double)(num_rings + 2));
  92.     dphi = (float)(2.0 * PI / (double) num_sections);
  93.     n = 1; /* vertex being generated, begins at 1 to skip top point */
  94.     theta = dtheta;
  95.     for (i = 0; i <= num_rings; i++) {
  96.         y = sphere_r * (float)cos(theta); /* y is the same for each ring */
  97.         v = theta / (float)PI;     /* v is the same for each ring */
  98.         rsintheta = sphere_r * (float)sin(theta);
  99.         phi = (float)0.0;
  100.         for (j = 0; j < num_sections; j++) {
  101.             x = rsintheta * (float)sin(phi);
  102.             z = rsintheta * (float)cos(phi);
  103.             lpv[n].x = D3DVAL(sx * x);
  104.             lpv[n].z = D3DVAL(sz * z);
  105.             lpv[n].y = D3DVAL(sy * y);
  106.             lpv[n].nx = D3DVAL(x / sphere_r);
  107.             lpv[n].ny = D3DVAL(y / sphere_r);
  108.             lpv[n].nz = D3DVAL(z / sphere_r);
  109.             lpv[n].tv = D3DVAL(v);
  110.             lpv[n].tu = D3DVAL((float)(1.0 - phi / (2.0 * PI)));
  111.             phi += dphi;
  112.             ++n;
  113.         }
  114.         theta += dtheta;
  115.     }
  116.  
  117.     /*
  118.      * Generate triangles for top and bottom caps.
  119.      */
  120.     if (num_sections < 30) {
  121.     /*
  122.      * we can put the whole cap in a tri fan.
  123.      */
  124.         for (i = 0; i < num_sections; i++) {
  125.             lptri[i].v1 = 0;
  126.             lptri[i].v2 = i + 1;
  127.             lptri[i].v3 = 1 + ((i + 1) % num_sections);
  128.             
  129.             lptri[num_tri - num_sections + i].v1 = num_v - 1;
  130.             lptri[num_tri - num_sections + i].v2 = num_v - 2 - i;
  131.             lptri[num_tri - num_sections + i].v3 = num_v - 2 - 
  132.                     ((1 + i) % num_sections);
  133.                     
  134.                    
  135.             /*
  136.              * Enable correct edges.
  137.              */
  138.             lptri[i].wFlags = D3DTRIFLAG_EDGEENABLE1 |
  139.                               D3DTRIFLAG_EDGEENABLE2;
  140.                               
  141.             lptri[num_tri - num_sections + i].wFlags= D3DTRIFLAG_EDGEENABLE1 |
  142.                                                       D3DTRIFLAG_EDGEENABLE2;
  143.             /*
  144.              * build fans.
  145.              */
  146.             if (i == 0) {
  147.                 lptri[i].wFlags |= D3DTRIFLAG_START;
  148.                 lptri[num_tri - num_sections + i].wFlags |= D3DTRIFLAG_START;
  149.             } else {
  150.                 lptri[i].wFlags |= D3DTRIFLAG_EVEN;
  151.                 lptri[num_tri - num_sections + i].wFlags |= D3DTRIFLAG_EVEN;
  152.             }
  153.             
  154.         }
  155.     } else {
  156.         for (i = 0; i < num_sections; i++) {
  157.             lptri[i].v1 = 0;
  158.             lptri[i].v2 = i + 1;
  159.             lptri[i].v3 = 1 + ((i + 1) % num_sections);
  160.             lptri[i].wFlags = D3DTRIFLAG_EDGEENABLE1;
  161.                               D3DTRIFLAG_EDGEENABLE2;
  162.             lptri[num_tri - num_sections + i].v1 = num_v - 1;
  163.             lptri[num_tri - num_sections + i].v2 = num_v - 2 - i;
  164.             lptri[num_tri - num_sections + i].v3 = num_v - 2 - 
  165.                     ((1 + i) % num_sections);
  166.             lptri[num_tri - num_sections + i].wFlags= D3DTRIFLAG_EDGEENABLE1 |
  167.                                                       D3DTRIFLAG_EDGEENABLE2;
  168.         }
  169.     }
  170.  
  171.     /*
  172.      * Generate triangles for the rings
  173.      */
  174.     m = 1; /* first vertex in current ring,begins at 1 to skip top point*/
  175.     n = num_sections; /* triangle being generated, skip the top cap */
  176.         for (i = 0; i < num_rings; i++) {
  177.         for (j = 0; j < num_sections; j++) {
  178.             lptri[n].v1 = m + j;
  179.             lptri[n].v2 = m + num_sections + j;
  180.             lptri[n].v3 = m + num_sections + ((j + 1) % num_sections);
  181.             lptri[n].wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE;
  182.             
  183.             /*
  184.              * Start a two triangle flat fan for each face.
  185.              */
  186.                     
  187.             lptri[n].wFlags = D3DTRIFLAG_STARTFLAT(1);
  188.             
  189.             /*
  190.              * only need two edges for wireframe.
  191.              */ 
  192.             lptri[n].wFlags |= D3DTRIFLAG_EDGEENABLE1 |
  193.                                D3DTRIFLAG_EDGEENABLE2;
  194.         
  195.             
  196.             lptri[n + 1].v1 = lptri[n].v1;
  197.             lptri[n + 1].v2 = lptri[n].v3;
  198.             lptri[n + 1].v3 = m + ((j + 1) % num_sections);
  199.             
  200.             lptri[n + 1].wFlags = D3DTRIFLAG_EVEN;
  201.             /*
  202.              * only need two edges for wireframe.
  203.              */ 
  204.             lptri[n + 1].wFlags |= D3DTRIFLAG_EDGEENABLE2 |
  205.                                    D3DTRIFLAG_EDGEENABLE3;
  206.             n += 2;
  207.         }
  208.         m += num_sections;
  209.     }
  210.     return TRUE;
  211. }
  212.