home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / SPD.3.0.shar.gz / SPD.3.0.shar / lib.c < prev    next >
C/C++ Source or Header  |  1991-01-13  |  17KB  |  662 lines

  1. /*
  2.  * lib.c - a library of common operations, and object output routines.
  3.  *
  4.  * Author:  Eric Haines, 3D/Eye, Inc.
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <math.h>
  9. #include "def.h"
  10. #include "lib.h"
  11.  
  12. /*
  13.  * Take the first argument on the command line as a size factor.
  14.  * No change if no/illegal argument found.
  15.  */
  16. int    lib_get_size( argc, argv, p_size )
  17. int    argc ;
  18. char    *argv[] ;
  19. int    *p_size ;
  20. {
  21. int    num ;
  22.  
  23.     if ( argc >= 2 ) {
  24.     if ( argc > 2 ) {
  25.         /* too many arguments */
  26.         return( FALSE ) ;
  27.     }
  28.     if ( sscanf( argv[1], "%d", &num ) == 1 ) {
  29.         if ( num > 0 ) {
  30.         *p_size = num ;
  31.         } else {
  32.         /* size <= 0 */
  33.         return( FALSE ) ;
  34.         }
  35.     } else {
  36.         /* unknown argument */
  37.         return( FALSE ) ;
  38.     }
  39.     }
  40.     return( TRUE ) ;
  41. }
  42.  
  43. /*
  44.  * Normalize the vector (X,Y,Z) so that X*X + Y*Y + Z*Z = 1.
  45.  *
  46.  * The normalization divisor is returned.  If the divisor is zero, no
  47.  * normalization occurs.
  48.  *
  49.  */
  50. double    lib_normalize_vector( cvec )
  51. COORD3    cvec ;
  52. {
  53. double    divisor ;
  54.  
  55.     divisor = sqrt( (double)DOT_PRODUCT( cvec, cvec ) ) ;
  56.  
  57.     if ( divisor != 0.0 ) {
  58.     cvec[X] /= divisor ;
  59.     cvec[Y] /= divisor ;
  60.     cvec[Z] /= divisor ;
  61.     }
  62.  
  63.     return( divisor ) ;
  64. }
  65.  
  66. /*
  67.  * Set all matrix elements to zero.
  68.  */
  69. lib_zero_matrix( mx )
  70. MATRIX    mx ;
  71. {
  72. int    i, j ;
  73.  
  74.     for ( i = 0 ; i < 4 ; ++i ) {
  75.     for ( j = 0 ; j < 4 ; ++j ) {
  76.         mx[i][j] = 0.0 ;
  77.     }
  78.     }
  79. }
  80.  
  81. /*
  82.  * Create identity matrix.
  83.  */
  84. lib_create_identity_matrix( mx )
  85. MATRIX    mx ;
  86. {
  87. int    i ;
  88.  
  89.     lib_zero_matrix( mx ) ;
  90.     for ( i = 0 ; i < 4 ; ++i ) {
  91.     mx[i][i] = 1.0 ;
  92.     }
  93. }
  94.  
  95. /*
  96.  * Create a rotation matrix along the given axis by the given angle in radians.
  97.  */
  98. lib_create_rotate_matrix( mx, axis, angle )
  99. MATRIX    mx ;
  100. int    axis ;
  101. double    angle ;
  102. {
  103. double    cosine, sine ;
  104.  
  105.     lib_zero_matrix( mx ) ;
  106.  
  107.     cosine = cos( (double)angle ) ;
  108.     sine = sin( (double)angle ) ;
  109.  
  110.     switch ( axis ) {
  111.     case X_AXIS:
  112.         mx[0][0] = 1.0 ;
  113.         mx[1][1] = mx[2][2] = cosine ;
  114.         mx[1][2] = sine ;
  115.         mx[2][1] = -sine ;
  116.         break ;
  117.     case Y_AXIS:
  118.         mx[1][1] = 1.0 ;
  119.         mx[0][0] = mx[2][2] = cosine ;
  120.         mx[2][0] = sine ;
  121.         mx[0][2] = -sine ;
  122.         break ;
  123.     case Z_AXIS:
  124.         mx[2][2] = 1.0 ;
  125.         mx[0][0] = mx[1][1] = cosine ;
  126.         mx[0][1] = sine ;
  127.         mx[1][0] = -sine ;
  128.         break ;
  129.     }
  130.     mx[3][3] = 1.0 ;
  131. }
  132.  
  133. /*
  134.  * Create a rotation matrix along the given axis by the given angle in radians.
  135.  * The axis is a set of direction cosines.
  136.  */
  137. lib_create_axis_rotate_matrix( mx, axis, angle )
  138. MATRIX    mx ;
  139. COORD3    axis ;
  140. double    angle ;
  141. {
  142. double    cosine, one_minus_cosine, sine ;
  143.  
  144.     lib_zero_matrix( mx ) ;
  145.  
  146.     cosine = cos( (double)angle ) ;
  147.     sine = sin( (double)angle ) ;
  148.     one_minus_cosine = 1.0 - cosine ;
  149.  
  150.     mx[0][0] = SQR(axis[X]) + (1.0 - SQR(axis[X])) * cosine ;
  151.     mx[0][1] = axis[X] * axis[Y] * one_minus_cosine + axis[Z] * sine ;
  152.     mx[0][2] = axis[X] * axis[Z] * one_minus_cosine - axis[Y] * sine ;
  153.  
  154.     mx[1][0] = axis[X] * axis[Y] * one_minus_cosine - axis[Z] * sine ;
  155.     mx[1][1] = SQR(axis[Y]) + (1.0 - SQR(axis[Y])) * cosine ;
  156.     mx[1][2] = axis[Y] * axis[Z] * one_minus_cosine + axis[X] * sine ;
  157.  
  158.     mx[2][0] = axis[X] * axis[Z] * one_minus_cosine + axis[Y] * sine ;
  159.     mx[2][1] = axis[Y] * axis[Z] * one_minus_cosine - axis[X] * sine ;
  160.     mx[2][2] = SQR(axis[Z]) + (1.0 - SQR(axis[Z])) * cosine ;
  161.  
  162.     mx[3][3] = 1.0 ;
  163. }
  164.  
  165. /*
  166.  * Multiply a vector by a matrix.
  167.  */
  168. lib_transform_vector( vres, vec, mx )
  169. COORD3    vres ;
  170. COORD3    vec ;
  171. MATRIX    mx ;
  172. {
  173.     vres[X] =
  174.     vec[X]*mx[0][0] + vec[Y]*mx[1][0] + vec[Z]*mx[2][0] ;
  175.     vres[Y] =
  176.     vec[X]*mx[0][1] + vec[Y]*mx[1][1] + vec[Z]*mx[2][1] ;
  177.     vres[Z] =
  178.     vec[X]*mx[0][2] + vec[Y]*mx[1][2] + vec[Z]*mx[2][2] ;
  179. }
  180.  
  181. /*
  182.  * Multiply a point by a matrix.
  183.  */
  184. lib_transform_point( vres, vec, mx )
  185. COORD3    vres ;
  186. COORD3    vec ;
  187. MATRIX    mx ;
  188. {
  189.     vres[X] =
  190.     vec[X]*mx[0][0] + vec[Y]*mx[1][0] + vec[Z]*mx[2][0] + mx[3][0] ;
  191.     vres[Y] =
  192.     vec[X]*mx[0][1] + vec[Y]*mx[1][1] + vec[Z]*mx[2][1] + mx[3][1] ;
  193.     vres[Z] =
  194.     vec[X]*mx[0][2] + vec[Y]*mx[1][2] + vec[Z]*mx[2][2] + mx[3][2] ;
  195. }
  196.  
  197. /*
  198.  * Multiply a 4 element vector by a matrix.
  199.  */
  200. lib_transform_coord( vres, vec, mx )
  201. COORD4    vres ;
  202. COORD4    vec ;
  203. MATRIX    mx ;
  204. {
  205.     vres[X] =
  206.     vec[X]*mx[0][0] + vec[Y]*mx[1][0] + vec[Z]*mx[2][0] + vec[W]*mx[3][0] ;
  207.     vres[Y] =
  208.     vec[X]*mx[0][1] + vec[Y]*mx[1][1] + vec[Z]*mx[2][1] + vec[W]*mx[3][1] ;
  209.     vres[Z] =
  210.     vec[X]*mx[0][2] + vec[Y]*mx[1][2] + vec[Z]*mx[2][2] + vec[W]*mx[3][2] ;
  211.     vres[W] =
  212.     vec[X]*mx[0][3] + vec[Y]*mx[1][3] + vec[Z]*mx[2][3] + vec[W]*mx[3][3] ;
  213. }
  214.  
  215. /*
  216.  * Compute transpose of matrix.
  217.  */
  218. lib_transpose_matrix( mxres, mx )
  219. MATRIX    mxres ;
  220. MATRIX    mx ;
  221. {
  222. int    i, j ;
  223.  
  224.     for ( i = 0 ; i < 4 ; ++i ) {
  225.     for ( j = 0 ; j < 4 ; ++j ) {
  226.         mxres[j][i] = mx[i][j] ;
  227.     }
  228.     }
  229. }
  230.  
  231. /*
  232.  * Multiply two 4x4 matrices.
  233.  */
  234. lib_matrix_multiply( mxres, mx1, mx2 )
  235. MATRIX    mxres ;
  236. MATRIX    mx1 ;
  237. MATRIX    mx2 ;
  238. {
  239. int    i, j ;
  240.  
  241.     for ( i = 0 ; i < 4 ; i++ ) {
  242.     for ( j = 0 ; j < 4 ; j++ ) {
  243.         mxres[i][j] = mx1[i][0]*mx2[0][j] +
  244.               mx1[i][1]*mx2[1][j] +
  245.               mx1[i][2]*mx2[2][j] +
  246.               mx1[i][3]*mx2[3][j] ;
  247.     }
  248.     }
  249. }
  250.  
  251. /*
  252.  * Rotate a vector pointing towards the major-axis faces (i.e. the major-axis
  253.  * component of the vector is defined as the largest value) 90 degrees to
  254.  * another cube face.  Mod_face is a face number.
  255.  *
  256.  * If the routine is called six times, with mod_face=0..5, the vector will be
  257.  * rotated to each face of a cube.  Rotations are:
  258.  *    mod_face = 0 mod 3, +Z axis rotate
  259.  *    mod_face = 1 mod 3, +X axis rotate
  260.  *    mod_face = 2 mod 3, -Y axis rotate
  261.  */
  262. lib_rotate_cube_face( vec, major_axis, mod_face )
  263. COORD3    vec ;
  264. int    major_axis ;
  265. int    mod_face ;
  266. {
  267. double    swap ;
  268.  
  269.     mod_face = (mod_face+major_axis) % 3 ;
  270.     if ( mod_face == 0 ) {
  271.     swap   = vec[X] ;
  272.     vec[X] = -vec[Y] ;
  273.     vec[Y] = swap ;
  274.     }
  275.     else if ( mod_face == 1 ) {
  276.     swap   = vec[Y] ;
  277.     vec[Y] = -vec[Z] ;
  278.     vec[Z] = swap ;
  279.     }
  280.     else {
  281.     swap   = vec[X] ;
  282.     vec[X] = -vec[Z] ;
  283.     vec[Z] = swap ;
  284.     }
  285. }
  286.  
  287. /*
  288.  * Portable gaussian random number generator (from "Numerical Recipes", GASDEV)
  289.  * Returns a uniform random deviate between 0.0 and 1.0.  'iseed' must be
  290.  * less than M1 to avoid repetition, and less than (2**31-C1)/A1 [= 300718]
  291.  * to avoid overflow.
  292.  */
  293. #define    M1    134456
  294. #define    IA1    8121
  295. #define    IC1    28411
  296. #define    RM1    1.0/M1
  297.  
  298. double    lib_gauss_rand(iseed)
  299. int    iseed ;
  300. {
  301. int    ix1, ix2 ;
  302. double    fac, r, v1, v2 ;
  303.  
  304.     ix2 = iseed ;
  305.  
  306.     do {
  307.     ix1 = (IC1+ix2*IA1) % M1 ;
  308.     ix2 = (IC1+ix1*IA1) % M1 ;
  309.     v1 = ix1 * 2.0 * RM1 - 1.0 ;
  310.     v2 = ix2 * 2.0 * RM1 - 1.0 ;
  311.     r = v1*v1 + v2*v2 ;
  312.     } while ( r >= 1.0 ) ;
  313.  
  314.     fac = sqrt( (double)( -2.0 * log( (double)r ) / r ) ) ;
  315.     return( v1 * fac ) ;
  316. }
  317.  
  318.  
  319. /* OUTPUT ROUTINES
  320.  *
  321.  * Files are output as lines of text.  For each entity, the first line
  322.  * defines its type.  The rest of the first line and possibly other lines
  323.  * contain further information about the entity.  Entities include:
  324.  *
  325.  * "v"  - viewing vectors and angles
  326.  * "l"  - positional light location
  327.  * "b"  - background color
  328.  * "f"  - object material properties
  329.  * "c"  - cone or cylinder primitive
  330.  * "s"  - sphere primitive
  331.  * "p"  - polygon primitive
  332.  * "pp" - polygonal patch primitive
  333.  */
  334.  
  335. /*
  336.  * Output viewpoint location.  The parameters are:
  337.  *   From:  the eye location.
  338.  *   At:  a position to be at the center of the image.  A.k.a. "lookat"
  339.  *   Up:  a vector defining which direction is up.
  340.  *
  341.  * Note that no assumptions are made about normalizing the data (e.g. the
  342.  * from-at distance does not have to be 1).  Also, vectors are not
  343.  * required to be perpendicular to each other.
  344.  *
  345.  * For all databases some viewing parameters are always the same:
  346.  *
  347.  * Viewing angle is defined as from the center of top pixel row to bottom
  348.  *    pixel row and left column to right column.
  349.  * Yon is "at infinity."
  350.  * Resolution is always 512 x 512.
  351.  */
  352. lib_output_viewpoint( from, at, up, angle, hither, resx, resy )
  353. COORD3    from ;
  354. COORD3    at ;
  355. COORD3    up ;
  356. double    angle ;
  357. double    hither ;
  358. int    resx ;
  359. int    resy ;
  360. {
  361.     printf( "v\n" ) ;
  362.     printf( "from %g %g %g\n", from[X], from[Y], from[Z] ) ;
  363.     printf( "at %g %g %g\n", at[X], at[Y], at[Z] ) ;
  364.     printf( "up %g %g %g\n", up[X], up[Y], up[Z] ) ;
  365.     printf( "angle %g\n", angle ) ;
  366.     printf( "hither %g\n", hither ) ;
  367.     printf( "resolution %d %d\n", resx, resy ) ;
  368. }
  369.  
  370. /*
  371.  * Output light.  A light is defined by position.  All lights have the same
  372.  * intensity.
  373.  *
  374.  */
  375. lib_output_light( center_pt )
  376. COORD3     center_pt ;
  377. {
  378.     printf( "l %g %g %g\n", center_pt[X], center_pt[Y], center_pt[Z] ) ;
  379. }
  380.  
  381. /*
  382.  * Output background color.  A color is simply RGB (monitor dependent, but
  383.  * that's life).  The format is:
  384.  *    "b" red green blue
  385.  */
  386. lib_output_background_color( color )
  387. COORD3     color ;
  388. {
  389.     printf( "b %g %g %g\n", color[X], color[Y], color[Z] ) ;
  390. }
  391.  
  392. /*
  393.  * Output a color and shading parameters for the object in the format:
  394.  *    "f" red green blue Kd Ks Shine T index_of_refraction
  395.  *
  396.  * Kd is the diffuse component, Ks the specular, Shine is the Phong cosine
  397.  * power for highlights, T is transmittance (fraction of light passed per
  398.  * unit).  0 <= Kd <= 1 and 0 <= Ks <= 1, though it is not required that
  399.  * Kd + Ks == 1.
  400.  *
  401.  * The fill color is used to color the objects following it until a new color
  402.  * is assigned or the file ends.
  403.  */
  404. lib_output_color( color, kd, ks, shine, t, i_of_r )
  405. COORD3     color ;
  406. double    kd ;
  407. double    ks ;
  408. double    shine ;
  409. double    t ;
  410. double    i_of_r ;
  411. {
  412.     printf( "f %g %g %g %g %g %g %g %g\n", color[X], color[Y], color[Z],
  413.                         kd, ks, shine, t, i_of_r ) ;
  414. }
  415.  
  416. /*
  417.  * Output cylinder or cone.  A cylinder is defined as having a radius and an
  418.  * axis defined by two points, which also define the top and bottom edge of the
  419.  * cylinder.  A cone is defined similarly, the difference being that the apex
  420.  * and base radii are different.  The apex radius is defined as being smaller
  421.  * than the base radius.  Note that the surface exists without endcaps.
  422.  *
  423.  * If format=OUTPUT_CURVES, output the cylinder/cone in format:
  424.  *    "c"
  425.  *    base[X] base[Y] base[Z] base_radius
  426.  *    apex[X] apex[Y] apex[Z] apex_radius
  427.  *
  428.  * If the format=OUTPUT_PATCHES, the surface is polygonalized and output.
  429.  * (4*OUTPUT_RESOLUTION) polygons are output as rectangles by
  430.  * lib_output_polypatch.
  431.  */
  432. lib_output_cylcone( base_pt, apex_pt, format )
  433. COORD4    base_pt ;
  434. COORD4    apex_pt ;
  435. int    format ;
  436. {
  437. int    num_pol ;
  438. double    angle, divisor ;
  439. COORD3    axis, dir ;
  440. COORD3    norm_axis, start_norm, start_radius[4] ;
  441. COORD3    lip_norm[4], lip_pt[4] ;
  442. MATRIX    mx ;
  443.  
  444.     if ( format == OUTPUT_CURVES ) {
  445.     printf( "c\n" ) ;
  446.     printf( "%g %g %g %g\n",
  447.         base_pt[X], base_pt[Y], base_pt[Z], base_pt[W] ) ;
  448.     printf( "%g %g %g %g\n",
  449.         apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W] ) ;
  450.     }
  451.     else {
  452.     SUB3_COORD3( axis, apex_pt, base_pt ) ;
  453.     COPY_COORD3( norm_axis, axis ) ;
  454.     (void)lib_normalize_vector( norm_axis ) ;
  455.  
  456.     SET_COORD3( dir, 0.0, 0.0, 1.0 ) ;
  457.     CROSS( start_norm, axis, dir ) ;
  458.  
  459.     divisor = lib_normalize_vector( start_norm ) ;
  460.     if ( ABSOLUTE( divisor ) < EPSILON ) {
  461.         SET_COORD3( dir, 1.0, 0.0, 0.0 ) ;
  462.         CROSS( start_norm, axis, dir ) ;
  463.         (void)lib_normalize_vector( start_norm ) ;
  464.     }
  465.  
  466.     start_radius[0][X] = start_norm[X] * base_pt[W] ;
  467.     start_radius[0][Y] = start_norm[Y] * base_pt[W] ;
  468.     start_radius[0][Z] = start_norm[Z] * base_pt[W] ;
  469.     ADD3_COORD3( lip_pt[0], base_pt, start_radius[0] ) ;
  470.  
  471.     start_radius[1][X] = start_norm[X] * apex_pt[W] ;
  472.     start_radius[1][Y] = start_norm[Y] * apex_pt[W] ;
  473.     start_radius[1][Z] = start_norm[Z] * apex_pt[W] ;
  474.     ADD3_COORD3( lip_pt[1], apex_pt, start_radius[1] ) ;
  475.  
  476.     COPY_COORD3( lip_norm[0], start_norm ) ;
  477.     COPY_COORD3( lip_norm[1], start_norm ) ;
  478.  
  479.     for ( num_pol = 0 ; num_pol < 4*OUTPUT_RESOLUTION ; ++num_pol ) {
  480.         COPY_COORD3( lip_pt[3], lip_pt[0] ) ;
  481.         COPY_COORD3( lip_pt[2], lip_pt[1] ) ;
  482.         COPY_COORD3( lip_norm[3], lip_norm[0] ) ;
  483.         COPY_COORD3( lip_norm[2], lip_norm[1] ) ;
  484.  
  485.         angle = 2.0 * PI *
  486.             (double)( num_pol+1 ) / (double)( 4*OUTPUT_RESOLUTION ) ;
  487.         lib_create_axis_rotate_matrix( mx, norm_axis, angle ) ;
  488.  
  489.         lib_transform_vector( lip_pt[0], start_radius[0], mx ) ;
  490.         ADD2_COORD3( lip_pt[0], base_pt ) ;
  491.         lib_transform_vector( lip_pt[1], start_radius[1], mx ) ;
  492.         ADD2_COORD3( lip_pt[1], apex_pt ) ;
  493.  
  494.         lib_transform_vector( lip_norm[0], start_norm, mx ) ;
  495.         COPY_COORD3( lip_norm[1], lip_norm[0] ) ;
  496.  
  497.         lib_output_polypatch( 4, lip_pt, lip_norm ) ;
  498.     }
  499.     }
  500. }
  501.  
  502. /*
  503.  * Output sphere.  A sphere is defined by a radius and center position.
  504.  *
  505.  * If format=OUTPUT_CURVES, output the sphere in format:
  506.  *    "s" center[X] center[Y] center[Z] radius
  507.  *
  508.  * If the format=OUTPUT_PATCHES, the sphere is polygonalized and output.
  509.  * The sphere is polygonalized by splitting it into 6 faces (of a cube
  510.  * projected onto the sphere) and dividing these faces by equally spaced
  511.  * great circles.  OUTPUT_RESOLUTION affects the number of great circles.
  512.  * (6*2*OUTPUT_RESOLUTION*OUTPUT_RESOLUTION) polygons are output as triangles
  513.  * using lib_output_polypatch.
  514.  */
  515. lib_output_sphere( center_pt, format )
  516. COORD4    center_pt ;
  517. int    format ;
  518. {
  519. int    num_face, num_edge, num_tri, num_vert, u_pol, v_pol ;
  520. double    angle ;
  521. COORD3    edge_norm[3], edge_pt[3] ;
  522. COORD3    x_axis[OUTPUT_RESOLUTION+1], y_axis[OUTPUT_RESOLUTION+1] ;
  523. COORD3    pt[OUTPUT_RESOLUTION+1][OUTPUT_RESOLUTION+1] ;
  524. COORD3    mid_axis ;
  525. MATRIX    rot_mx ;
  526.  
  527.     if ( format == OUTPUT_CURVES ) {
  528.     printf( "s %g %g %g %g\n",
  529.         center_pt[X], center_pt[Y], center_pt[Z], center_pt[W] ) ;
  530.     }
  531.     else {
  532.     /* calculate axes used to find grid points */
  533.     for ( num_edge = 0 ; num_edge <= OUTPUT_RESOLUTION ; ++num_edge ) {
  534.         angle = (PI/4.0) * (2.0*(double)num_edge/OUTPUT_RESOLUTION - 1.0) ;
  535.  
  536.         mid_axis[X] = 1.0 ; mid_axis[Y] = 0.0 ; mid_axis[Z] = 0.0 ;
  537.         lib_create_rotate_matrix( rot_mx, Y_AXIS, angle ) ;
  538.         lib_transform_vector( x_axis[num_edge], mid_axis, rot_mx ) ;
  539.  
  540.         mid_axis[X] = 0.0 ; mid_axis[Y] = 1.0 ; mid_axis[Z] = 0.0 ;
  541.         lib_create_rotate_matrix( rot_mx, X_AXIS, angle ) ;
  542.         lib_transform_vector( y_axis[num_edge], mid_axis, rot_mx ) ;
  543.     }
  544.  
  545.     /* set up grid of points on +Z sphere surface */
  546.     for ( u_pol = 0 ; u_pol <= OUTPUT_RESOLUTION ; ++u_pol ) {
  547.         for ( v_pol = 0 ; v_pol <= OUTPUT_RESOLUTION ; ++v_pol ) {
  548.         CROSS( pt[u_pol][v_pol], x_axis[u_pol], y_axis[v_pol] ) ;
  549.         (void)lib_normalize_vector( pt[u_pol][v_pol] ) ;
  550.         }
  551.     }
  552.     for ( num_face = 0 ; num_face < 6 ; ++num_face ) {
  553.         /* transform points to cube face */
  554.         for ( u_pol = 0 ; u_pol <= OUTPUT_RESOLUTION ; ++u_pol ) {
  555.         for ( v_pol = 0 ; v_pol <= OUTPUT_RESOLUTION ; ++v_pol ) {
  556.             lib_rotate_cube_face( pt[u_pol][v_pol]
  557.                     , Z_AXIS
  558.                     , num_face
  559.                     ) ;
  560.         }
  561.         }
  562.         /* output grid */
  563.         for ( u_pol = 0 ; u_pol < OUTPUT_RESOLUTION ; ++u_pol ) {
  564.         for ( v_pol = 0 ; v_pol < OUTPUT_RESOLUTION ; ++v_pol ) {
  565.             for ( num_tri = 0 ; num_tri < 2 ; ++num_tri ) {
  566.             for ( num_edge = 0 ; num_edge < 3 ; ++num_edge ) {
  567.                 num_vert = (num_tri*2 + num_edge) % 4 ;
  568.                 if ( num_vert == 0 ) {
  569.                 COPY_COORD3( edge_pt[num_edge]
  570.                        , pt[u_pol][v_pol] ) ;
  571.                 }
  572.                 else if ( num_vert == 1 ) {
  573.                 COPY_COORD3( edge_pt[num_edge]
  574.                        , pt[u_pol][v_pol+1] ) ;
  575.                 }
  576.                 else if ( num_vert == 2 ) {
  577.                 COPY_COORD3( edge_pt[num_edge]
  578.                        , pt[u_pol+1][v_pol+1] ) ;
  579.                 }
  580.                 else {
  581.                 COPY_COORD3( edge_pt[num_edge]
  582.                        , pt[u_pol+1][v_pol] ) ;
  583.                 }
  584.                 COPY_COORD3( edge_norm[num_edge]
  585.                        , edge_pt[num_edge] ) ;
  586.                 edge_pt[num_edge][X] =
  587.                     edge_pt[num_edge][X] * center_pt[W] +
  588.                                center_pt[X] ;
  589.                 edge_pt[num_edge][Y] =
  590.                     edge_pt[num_edge][Y] * center_pt[W] +
  591.                                center_pt[Y] ;
  592.                 edge_pt[num_edge][Z] =
  593.                     edge_pt[num_edge][Z] * center_pt[W] +
  594.                                center_pt[Z] ;
  595.  
  596.             }
  597.             lib_output_polypatch( 3, edge_pt, edge_norm ) ;
  598.             }
  599.         }
  600.         }
  601.     }
  602.     }
  603. }
  604.  
  605. /*
  606.  * Output polygon.  A polygon is defined by a set of vertices.  With these
  607.  * databases, a polygon is defined to have all points coplanar.  A polygon has
  608.  * only one side, with the order of the vertices being counterclockwise as you
  609.  * face the polygon (right-handed coordinate system).
  610.  *
  611.  * The output format is always:
  612.  *    "p" total_vertices
  613.  *    vert1[X] vert1[Y] vert1[Z]
  614.  *    [etc. for total_vertices polygons]
  615.  *
  616.  */
  617. lib_output_polygon( tot_vert, vert )
  618. int    tot_vert ;
  619. COORD3     vert[] ;
  620. {
  621. int    num_vert ;
  622.  
  623.     printf( "p %d\n", tot_vert ) ;
  624.  
  625.     for ( num_vert = 0 ; num_vert < tot_vert ; ++num_vert ) {
  626.     printf( "%g %g %g\n", vert[num_vert][X]
  627.                 , vert[num_vert][Y]
  628.                 , vert[num_vert][Z] ) ;
  629.     }
  630. }
  631.  
  632. /*
  633.  * Output polygonal patch.  A patch is defined by a set of vertices and their
  634.  * normals.  With these databases, a patch is defined to have all points
  635.  * coplanar.  A patch has only one side, with the order of the vertices being
  636.  * counterclockwise as you face the patch (right-handed coordinate system).
  637.  *
  638.  * The output format is always:
  639.  *    "pp" total_vertices
  640.  *    vert1[X] vert1[Y] vert1[Z] norm1[X] norm1[Y] norm1[Z]
  641.  *    [etc. for total_vertices polygonal patches]
  642.  *
  643.  */
  644. lib_output_polypatch( tot_vert, vert, norm )
  645. int    tot_vert ;
  646. COORD3    vert[] ;
  647. COORD3    norm[] ;
  648. {
  649. int    num_vert ;
  650.  
  651.     printf( "pp %d\n", tot_vert ) ;
  652.  
  653.     for ( num_vert = 0 ; num_vert < tot_vert ; ++num_vert ) {
  654.     printf( "%g %g %g %g %g %g\n", vert[num_vert][X]
  655.                      , vert[num_vert][Y]
  656.                      , vert[num_vert][Z]
  657.                      , norm[num_vert][X]
  658.                      , norm[num_vert][Y]
  659.                      , norm[num_vert][Z] ) ;
  660.     }
  661. }
  662.