home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 September / macformat-041.iso / mac / Shareware City / Graphics / MacSPD / Sources / libpr1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-04  |  29.5 KB  |  1,126 lines  |  [TEXT/MMCC]

  1. /*
  2.  * libpr1.c - a library of primitive object output routines, part 1 of 3.
  3.  *
  4.  * Author:  Eric Haines, 3D/Eye, Inc.
  5.  *
  6.  */
  7.  
  8. /*-----------------------------------------------------------------*/
  9. /* include section */
  10. /*-----------------------------------------------------------------*/
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <math.h>
  15. #include <string.h>
  16.  
  17. #include "lib.h"
  18. #include "drv.h"
  19.  
  20.  
  21. /*-----------------------------------------------------------------*/
  22. /* defines/constants section */
  23. /*-----------------------------------------------------------------*/
  24.  
  25.  
  26. /*-----------------------------------------------------------------*/
  27. void lib_output_comment (comment)
  28.     char *comment;
  29. {
  30.     switch (gRT_out_format) {
  31.  
  32.     case OUTPUT_VIDEO:
  33.     case OUTPUT_DELAYED:
  34.     case OUTPUT_RAWTRI:
  35.     case OUTPUT_DXF:        /* well, there's the 999 format, but... >>>>> */
  36.     case OUTPUT_RWX:
  37.         /* no comments allowed for these file formats */
  38.         break;
  39.  
  40.     case OUTPUT_NFF:
  41.     case OUTPUT_OBJ:
  42.     case OUTPUT_RIB:
  43.         fprintf(gOutfile, "# %s\n", comment);
  44.         break;
  45.  
  46.     case OUTPUT_RAYSHADE:
  47.     case OUTPUT_POLYRAY:
  48.     case OUTPUT_POVRAY_10:
  49.     case OUTPUT_POVRAY_20:
  50.         fprintf(gOutfile, "// %s\n", comment);
  51.         break;
  52.  
  53.     /* unknown comment formats... whoever knows, please fix or fill in! */
  54.     case OUTPUT_PLG:
  55.     case OUTPUT_VIVID:
  56.     case OUTPUT_RTRACE:
  57.     case OUTPUT_QRT:
  58.     case OUTPUT_ART:
  59.     default:
  60.         fprintf(gOutfile, "// <comment> '%s'\n", comment);
  61.         break;
  62.  
  63.     }
  64. } /* lib_output_comment */
  65.  
  66.  
  67. /*-----------------------------------------------------------------*/
  68. void lib_output_vector(x, y, z)
  69. double  x, y, z;
  70. {
  71.     switch (gRT_out_format) {
  72.     case OUTPUT_VIDEO:
  73.     case OUTPUT_DELAYED:
  74.     case OUTPUT_DXF:
  75.     case OUTPUT_RWX:
  76.         break;
  77.  
  78.     case OUTPUT_PLG:
  79.     case OUTPUT_OBJ:
  80.     case OUTPUT_NFF:
  81.     case OUTPUT_VIVID:
  82.     case OUTPUT_RAYSHADE:
  83.     case OUTPUT_RTRACE:
  84.     case OUTPUT_RAWTRI:
  85.         fprintf(gOutfile, "%g %g %g", x, y, z);
  86.         break;
  87.  
  88.     case OUTPUT_POVRAY_10:
  89.         fprintf(gOutfile, "<%g %g %g>", x, y, z);
  90.         break;
  91.     case OUTPUT_POVRAY_20:
  92.         fprintf(gOutfile, "<%g, %g, %g>", x, y, z);
  93.         break;
  94.  
  95.     case OUTPUT_POLYRAY:
  96.     case OUTPUT_QRT:
  97.     case OUTPUT_ART:
  98.         fprintf(gOutfile, "%g, %g, %g", x, y, z);
  99.         break;
  100.     }
  101. } /* lib_output_vector */
  102.  
  103.  
  104. /*-----------------------------------------------------------------*/
  105. void
  106. axis_to_z(axis, xang, yang)
  107.      COORD3 axis;
  108.      double *xang, *yang;
  109. {
  110.   double len;
  111.  
  112.   /* The axis is in RH coordinates and turns the axis to Z axis */
  113.   /* The angles are for the LH coordinate system */
  114.   len = sqrt(axis[X] * axis[X] + axis[Z] * axis[Z]);
  115.   *xang = -180.0 * asin(axis[Y]) / PI;
  116.   if (len < EPSILON)
  117.     *yang = 0.0;
  118.   else
  119.     *yang = 180.0 * acos(axis[Z] / len) / PI;
  120.   if (axis[X] < 0)
  121.     *yang = -(*yang);
  122. } /* axis_to_z */
  123.  
  124. /*-----------------------------------------------------------------*/
  125. /*
  126.  * Output viewpoint location.  The parameters are:
  127.  *   From:   The eye location.
  128.  *   At:     A position to be at the center of the image.  A.k.a. "lookat"
  129.  *   Up:     A vector defining which direction is up.
  130.  *   Fov:    Vertical field of view of the camera
  131.  *   Aspect: Aspect ratio of horizontal fov to vertical fov
  132.  *   Hither: Minimum distance to any ray-surface intersection
  133.  *   Resx:   X resolution of resulting image
  134.  *   Resy:   Y resolution of resulting image
  135.  *
  136.  * For all databases some viewing parameters are always the same:
  137.  *
  138.  *   Viewing angle is defined as from the center of top pixel row to bottom
  139.  *     pixel row and left column to right column.
  140.  *   Yon is "at infinity."
  141.  */
  142. void
  143. lib_output_viewpoint(from, at, up,
  144.              fov_angle, aspect_ratio, hither,
  145.              resx, resy)
  146.     COORD3 from, at, up;
  147.     double fov_angle, aspect_ratio, hither;
  148.     int    resx, resy;
  149. {
  150.     COORD3 axis, myright, tmp;
  151.     COORD4 viewvec, rightvec;
  152.     MATRIX m1;
  153.     double tmpf;
  154.     double frustrumheight, frustrumwidth;
  155.  
  156.     switch (gRT_out_format) {
  157.     case OUTPUT_DELAYED:
  158.     case OUTPUT_VIDEO:
  159.     case OUTPUT_PLG:
  160.     case OUTPUT_OBJ:
  161.     case OUTPUT_RWX:
  162.         /* Save the various view parameters */
  163.         COPY_COORD3(gViewpoint.from, from);
  164.         COPY_COORD3(gViewpoint.at, at);
  165.         COPY_COORD3(gViewpoint.up, up);
  166.         gViewpoint.angle  = fov_angle;
  167.         gViewpoint.hither = hither;
  168.         gViewpoint.resx   = resx;
  169.         gViewpoint.resy   = resy;
  170.         gViewpoint.aspect = aspect_ratio;
  171.  
  172.         /* Make the 3D clipping box for this view */
  173.         gView_bounds[0][0] = 0;
  174.         gView_bounds[1][0] = gViewpoint.resx;
  175.         gView_bounds[0][1] = 0;
  176.         gView_bounds[1][1] = gViewpoint.resy;
  177.         gView_bounds[0][2] = gViewpoint.hither;
  178.         gView_bounds[1][2] = 1.0e10;
  179.  
  180.         /* Generate the perspective view matrix */
  181.         lib_create_view_matrix(gViewpoint.tx, gViewpoint.from, gViewpoint.at,
  182.                    gViewpoint.up, gViewpoint.resx, gViewpoint.resy,
  183.                    gViewpoint.angle, gViewpoint.aspect);
  184.  
  185.         /* Turn on graphics using system dependent video routines */
  186.         if (gRT_out_format == OUTPUT_VIDEO) {
  187.         display_init(gViewpoint.resx, gViewpoint.resy, gBkgnd_color);
  188.         gView_init_flag = 1;
  189.         }
  190.         break;
  191.  
  192.     case OUTPUT_NFF:
  193.         fprintf(gOutfile, "v\n");
  194.         fprintf(gOutfile, "from %g %g %g\n", from[X], from[Y], from[Z]);
  195.         fprintf(gOutfile, "at %g %g %g\n", at[X], at[Y], at[Z]);
  196.         fprintf(gOutfile, "up %g %g %g\n", up[X], up[Y], up[Z]);
  197.         fprintf(gOutfile, "angle %g\n", fov_angle);
  198.         fprintf(gOutfile, "hither %g\n", hither);
  199.         fprintf(gOutfile, "resolution %d %d\n", resx, resy);
  200.         break;
  201.  
  202.     case OUTPUT_POVRAY_10:
  203.     case OUTPUT_POVRAY_20:
  204.         /* Let's get a set of vectors that are all at right angles to each
  205.            other that describe the view given. */
  206.         lib_normalize_vector(up);
  207.         SUB3_COORD3(viewvec, at, from);
  208.         lib_normalize_vector(viewvec);
  209.         CROSS(rightvec, up, viewvec);
  210.         lib_normalize_vector(rightvec);
  211.         CROSS(up, viewvec, rightvec);
  212.         lib_normalize_vector(up);
  213.  
  214.         /* Calculate the height of the view frustrum in world coordinates.
  215.            and then scale the right and up vectors appropriately. */
  216.         frustrumheight = 2.0 * tan(PI * fov_angle / 360.0);
  217.         frustrumwidth = aspect_ratio * frustrumheight;
  218.         up[X] *= frustrumheight;
  219.         up[Y] *= frustrumheight;
  220.         up[Z] *= frustrumheight;
  221.         rightvec[X] *= frustrumwidth;
  222.         rightvec[Y] *= frustrumwidth;
  223.         rightvec[Z] *= frustrumwidth;
  224.  
  225.         tab_indent();
  226.         fprintf(gOutfile, "camera {\n");
  227.         tab_inc();
  228.  
  229.         if (gRT_out_format == OUTPUT_POVRAY_10) {
  230.         tab_indent();
  231.         fprintf(gOutfile, "location <%g %g %g>\n",
  232.             from[X], from[Y], from[Z]);
  233.         tab_indent();
  234.         fprintf(gOutfile, "direction <%g %g %g>\n",
  235.             viewvec[X], viewvec[Y], viewvec[Z]);
  236.         tab_indent();
  237.         fprintf(gOutfile, "right <%g %g %g>\n",
  238.             -rightvec[X], -rightvec[Y], -rightvec[Z]);
  239.         tab_indent();
  240.         fprintf(gOutfile, "up <%g %g %g>\n",
  241.             up[X], up[Y], up[Z]);
  242.         }
  243.         else {
  244.         tab_indent();
  245.         fprintf(gOutfile, "location <%g, %g, %g>\n",
  246.             from[X], from[Y], from[Z]);
  247.         tab_indent();
  248.         fprintf(gOutfile, "direction <%g, %g, %g>\n",
  249.             viewvec[X], viewvec[Y], viewvec[Z]);
  250.         tab_indent();
  251.         fprintf(gOutfile, "right <%g, %g, %g>\n",
  252.             -rightvec[X], -rightvec[Y], -rightvec[Z]);
  253.         tab_indent();
  254.         fprintf(gOutfile, "up <%g, %g, %g>\n",
  255.             up[X], up[Y], up[Z]);
  256.         }
  257.         tab_dec();
  258.         fprintf(gOutfile, "} // camera\n");
  259.         fprintf(gOutfile, "\n");
  260.         break;
  261.  
  262.     case OUTPUT_POLYRAY:
  263.         tab_indent();
  264.         fprintf(gOutfile, "viewpoint {\n");
  265.         tab_inc();
  266.  
  267.         tab_indent();
  268.         fprintf(gOutfile, "from <%g, %g, %g>\n", from[X], from[Y], from[Z]);
  269.         tab_indent();
  270.         fprintf(gOutfile, "at <%g, %g, %g>\n", at[X], at[Y], at[Z]);
  271.         tab_indent();
  272.         fprintf(gOutfile, "up <%g, %g, %g>\n", up[X], up[Y], up[Z]);
  273.         tab_indent();
  274.         fprintf(gOutfile, "angle %g\n", fov_angle);
  275.         tab_indent();
  276.         /* Note the negative, this is to change to right handed
  277.            coordinates (like most of the other tracers) */
  278.         fprintf(gOutfile, "aspect %g\n", -aspect_ratio);
  279.         tab_indent();
  280.         fprintf(gOutfile, "hither %g\n", hither);
  281.         tab_indent();
  282.         fprintf(gOutfile, "resolution %d, %d\n", resx, resy);
  283.  
  284.         tab_dec();
  285.         tab_indent();
  286.         fprintf(gOutfile, "}\n");
  287.         fprintf(gOutfile, "\n");
  288.         break;
  289.  
  290.     case OUTPUT_VIVID:
  291.         tab_indent();
  292.         fprintf(gOutfile, "studio {\n");
  293.         tab_inc();
  294.  
  295.         tab_indent();
  296.         fprintf(gOutfile, "from %g %g %g\n", from[X], from[Y], from[Z]);
  297.         tab_indent();
  298.         fprintf(gOutfile, "at %g %g %g\n", at[X], at[Y], at[Z]);
  299.         tab_indent();
  300.         fprintf(gOutfile, "up %g %g %g\n", up[X], up[Y], up[Z]);
  301.         tab_indent();
  302.         fprintf(gOutfile, "angle %g\n", fov_angle);
  303.         tab_indent();
  304.         fprintf(gOutfile, "aspect %g\n", aspect_ratio);
  305.         tab_indent();
  306.         fprintf(gOutfile, "resolution %d %d\n", resx, resy);
  307.         tab_indent();
  308.         fprintf(gOutfile, "no_exp_trans\n");
  309.  
  310.         tab_dec();
  311.         tab_indent();
  312.         fprintf(gOutfile, "}\n");
  313.         fprintf(gOutfile, "\n");
  314.         break;
  315.  
  316.     case OUTPUT_QRT:
  317.         tab_indent();
  318.         fprintf(gOutfile, "OBSERVER = (\n");
  319.         tab_inc();
  320.  
  321.         tab_indent();
  322.         fprintf(gOutfile, "loc = (%g,%g,%g),\n", from[X], from[Y], from[Z]);
  323.         tab_indent();
  324.         fprintf(gOutfile, "lookat = (%g,%g,%g),\n", at[X], at[Y], at[Z]);
  325.         tab_indent();
  326.         fprintf(gOutfile, "up = (%g,%g,%g)\n", up[X], up[Y], up[Z]);
  327.         tab_dec();
  328.         tab_indent();
  329.         fprintf(gOutfile, ")\n");
  330.  
  331.         tab_indent();
  332.         fprintf(gOutfile, "FOC_LENGTH = %g\n",
  333.             35.0 / tan(PI * fov_angle / 360.0));
  334.         tab_indent();
  335.         fprintf(gOutfile, "DEFAULT (\n");
  336.         tab_inc();
  337.         tab_indent();
  338.         fprintf(gOutfile, "aspect = %g,\n", 6.0 * aspect_ratio / 7.0);
  339.         tab_indent();
  340.         fprintf(gOutfile, "x_res = %d, y_res = %d\n", resx, resy);
  341.         tab_dec();
  342.         tab_indent();
  343.         fprintf(gOutfile, ")\n");
  344.  
  345.         /* QRT insists on having the output file as part of the data text */
  346.         tab_indent();
  347.         fprintf(gOutfile, "FILE_NAME = qrt.tga\n");
  348.         break;
  349.  
  350.     case OUTPUT_RAYSHADE:
  351.         fprintf(gOutfile, "eyep %g %g %g\n", from[X], from[Y], from[Z]);
  352.         fprintf(gOutfile, "lookp %g %g %g\n", at[X], at[Y], at[Z]);
  353.         fprintf(gOutfile, "up %g %g %g\n", up[X], up[Y], up[Z]);
  354.         fprintf(gOutfile, "fov %g %g\n", aspect_ratio * fov_angle,
  355.              fov_angle);
  356.         fprintf(gOutfile, "screen %d %d\n", resx, resy);
  357.         fprintf(gOutfile, "sample 1 nojitter\n");
  358.         break;
  359.  
  360.     case OUTPUT_RTRACE:
  361.         fprintf(gOutfile, "View\n");
  362.         fprintf(gOutfile, "%g %g %g\n", from[X], from[Y], from[Z]);
  363.         fprintf(gOutfile, "%g %g %g\n", at[X], at[Y], at[Z]);
  364.         fprintf(gOutfile, "%g %g %g\n", up[X], up[Y], up[Z]);
  365.         fprintf(gOutfile, "%g %g\n", aspect_ratio * fov_angle/2,
  366.              fov_angle/2);
  367.         break;
  368.  
  369.     case OUTPUT_ART:
  370.         fprintf(gOutfile, "maxhitlevel 4\n");
  371.         fprintf(gOutfile, "screensize 0.0, 0.0\n");
  372.         fprintf(gOutfile, "fieldofview %g\n", fov_angle);
  373.         fprintf(gOutfile, "up(%g, %g, %g)\n", up[X], up[Y], up[Z]);
  374.         fprintf(gOutfile, "lookat(%g, %g, %g, ", from[X], from[Y], from[Z]);
  375.         fprintf(gOutfile, "%g, %g, %g, 0.0)\n", at[X], at[Y], at[Z]);
  376.         fprintf(gOutfile, "\n");
  377.         break;
  378.  
  379.     case OUTPUT_RAWTRI:
  380.         break;
  381.  
  382.     case OUTPUT_RIB:
  383.         fprintf(gOutfile, "version 3.03\n");
  384.         fprintf(gOutfile, "FrameBegin 1\n");
  385.         fprintf(gOutfile, "Format %d %d 1\n", resx, resy);
  386.         fprintf(gOutfile, "PixelSamples 1 1\n");
  387.         fprintf(gOutfile, "ShadingRate 1.0\n");
  388.         fprintf(gOutfile, "Projection \"perspective\" \"fov\" %#g\n",
  389.             fov_angle);
  390.         fprintf(gOutfile, "Clipping %#g %#g\n\n", hither, 1e38);
  391.  
  392.         /* Calculate transformation from intrisic position */
  393.         SUB3_COORD3(axis, at, from);
  394.         lib_normalize_vector(axis);
  395.  
  396.         COPY_COORD3(tmp,axis);
  397.         tmpf = DOT_PRODUCT(up,axis);
  398.         tmp[0] *= tmpf;  tmp[1] *= tmpf;  tmp[2] *= tmpf;
  399.         SUB2_COORD3(up,tmp);
  400.         lib_normalize_vector(up);
  401.  
  402.         CROSS(myright,up,axis);
  403.         lib_normalize_vector (myright);
  404.  
  405.         m1[0][0] = myright[0];  m1[1][0] = myright[1];
  406.         m1[2][0] = myright[2];  m1[3][0] = 0;
  407.         m1[0][1] = up[0];  m1[1][1] = up[1];
  408.         m1[2][1] = up[2]; m1[3][1] = 0;
  409.         m1[0][2] = axis[0];  m1[1][2] = axis[1];
  410.         m1[2][2] = axis[2];  m1[3][2] = 0;
  411.         m1[0][3] = 0;  m1[1][3] = 0;  m1[2][3] = 0;  m1[3][3] = 1;
  412.         fprintf (gOutfile, "ConcatTransform [%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g]\n",
  413.              m1[0][0], m1[0][1], m1[0][2], m1[0][3],
  414.              m1[1][0], m1[1][1], m1[1][2], m1[1][3],
  415.              m1[2][0], m1[2][1], m1[2][2], m1[2][3],
  416.              m1[3][0], m1[3][1], m1[3][2], m1[3][3]);
  417.         fprintf (gOutfile, "Translate %g %g %g\n", -from[0], -from[1], -from[2]);
  418.  
  419.         fprintf(gOutfile, "WorldBegin\n");
  420.         tab_inc();
  421.         break ;
  422.  
  423.     case OUTPUT_DXF:
  424.         fprintf(gOutfile, "  0\n" ) ;
  425.         fprintf(gOutfile, "SECTION\n" ) ;
  426.         fprintf(gOutfile, "  2\n" ) ;
  427.         fprintf(gOutfile, "HEADER\n" ) ;
  428.         fprintf(gOutfile, "  0\n" ) ;
  429.         fprintf(gOutfile, "ENDSEC\n" ) ;
  430.         fprintf(gOutfile, "  0\n" ) ;
  431.         fprintf(gOutfile, "SECTION\n" ) ;
  432.         fprintf(gOutfile, "  2\n" ) ;
  433.         fprintf(gOutfile, "ENTITIES\n" ) ;
  434.         /* should add view someday ... */
  435.         break;
  436.     }
  437. }
  438.  
  439. /*-----------------------------------------------------------------*/
  440. /*
  441.  * Output light.  A light is defined by position.  All lights have the same
  442.  * intensity.
  443.  *
  444.  */
  445. void
  446. lib_output_light(center_pt)
  447.     COORD4 center_pt;
  448. {
  449.     COORD3 vec;
  450.     MATRIX txmat;
  451.     double lscale;
  452.     light_ptr new_light;
  453.  
  454.     if (center_pt[W] != 0.0)
  455.     lscale = center_pt[W];
  456.     else
  457.     lscale = 1.0;
  458.  
  459.     COPY_COORD3(vec, center_pt)
  460.     if (lib_tx_active()) {
  461.     /* Perform transformations of the vertices and normals of
  462.        the polygon(s) */
  463.     lib_get_current_tx(txmat);
  464.     lib_transform_vector(vec, vec, txmat);
  465.     }
  466.  
  467.     switch (gRT_out_format) {
  468.     case OUTPUT_DELAYED:
  469.         new_light = (light_ptr)malloc(sizeof(struct light_struct));
  470.         if (new_light == NULL)
  471.            /* Quietly fail & return */
  472.            return;
  473.         COPY_COORD4(new_light->center_pt, center_pt);
  474.         new_light->center_pt[W] = lscale;
  475.         new_light->next = gLib_lights;
  476.         gLib_lights = new_light;
  477.         break;
  478.  
  479.     case OUTPUT_VIDEO:
  480.     case OUTPUT_PLG:
  481.     case OUTPUT_OBJ:
  482.     case OUTPUT_RWX:
  483.         /* Not currently doing anything with lights */
  484.         break;
  485.  
  486.     case OUTPUT_NFF:
  487.         fprintf(gOutfile, "l %g %g %g\n",
  488.             vec[X], vec[Y], vec[Z]);
  489.         break;
  490.  
  491.     case OUTPUT_POVRAY_10:
  492.         tab_indent();
  493.         fprintf(gOutfile, "object {\n");
  494.         tab_inc();
  495.  
  496.         tab_indent();
  497.         fprintf(gOutfile, "light_source {\n");
  498.         tab_inc();
  499.  
  500.         tab_indent();
  501.         fprintf(gOutfile, "<%g %g %g>",
  502.             vec[X], vec[Y], vec[Z]);
  503.         fprintf(gOutfile, " color red %g green %g blue %g\n",
  504.             lscale, lscale, lscale);
  505.  
  506.         tab_dec();
  507.         tab_indent();
  508.         fprintf(gOutfile, "} // light\n");
  509.  
  510.         tab_dec();
  511.         tab_indent();
  512.         fprintf(gOutfile, "} // object\n");
  513.  
  514.         fprintf(gOutfile, "\n");
  515.         break;
  516.  
  517.     case OUTPUT_POVRAY_20:
  518.         tab_indent();
  519.         fprintf(gOutfile, "light_source {\n");
  520.         tab_inc();
  521.  
  522.         tab_indent();
  523.         fprintf(gOutfile, "<%g, %g, %g>",
  524.             vec[X], vec[Y], vec[Z]);
  525.         fprintf(gOutfile, " color red %g green %g blue %g\n",
  526.             lscale, lscale, lscale);
  527.  
  528.         tab_dec();
  529.         tab_indent();
  530.         fprintf(gOutfile, "} // light\n");
  531.  
  532.         fprintf(gOutfile, "\n");
  533.         break;
  534.  
  535.     case OUTPUT_POLYRAY:
  536.         tab_indent();
  537.         fprintf(gOutfile, "light <%g, %g, %g>, <%g, %g, %g>\n",
  538.             lscale, lscale, lscale,
  539.             vec[X], vec[Y], vec[Z]);
  540.         fprintf(gOutfile, "\n");
  541.         break;
  542.  
  543.     case OUTPUT_VIVID:
  544.         tab_indent();
  545.         fprintf(gOutfile, "light {type point position %g %g %g",
  546.             vec[X], vec[Y], vec[Z]);
  547.         fprintf(gOutfile, " color %g %g %g }\n",
  548.             lscale, lscale, lscale);
  549.         fprintf(gOutfile, "\n");
  550.         break;
  551.  
  552.     case OUTPUT_QRT:
  553.         tab_indent();
  554.         fprintf(gOutfile, "LAMP ( loc = (%g,%g,%g), dist = 0, radius = 1,",
  555.             vec[X], vec[Y], vec[Z]);
  556.         fprintf(gOutfile, " amb = (%g,%g,%g) )\n",
  557.             lscale, lscale, lscale);
  558.         break;
  559.  
  560.     case OUTPUT_RAYSHADE:
  561.         fprintf(gOutfile, "light %g point %g %g %g\n",
  562.             lscale, vec[X], vec[Y], vec[Z]);
  563.         break;
  564.  
  565.     case OUTPUT_RTRACE:
  566.         fprintf(gOutfile, "1 %g %g %g %g %g %g\n",
  567.         vec[X], vec[Y], vec[Z], lscale, lscale, lscale);
  568.         break;
  569.  
  570.     case OUTPUT_ART:
  571.         tab_indent();
  572.         fprintf(gOutfile, "light \n{");
  573.         tab_inc();
  574.  
  575.         tab_indent();
  576.         fprintf(gOutfile, "location(%g, %g, %g)  colour 0.5, 0.5, 0.5\n",
  577.            vec[X], vec[Y], vec[Z]);
  578.  
  579.         tab_dec();
  580.         tab_indent();
  581.         fprintf(gOutfile, "}\n");
  582.         fprintf(gOutfile, "\n");
  583.         break;
  584.  
  585.     case OUTPUT_RAWTRI:
  586.     case OUTPUT_DXF:
  587.         break;
  588.  
  589.     case OUTPUT_RIB:
  590.       {
  591.         static int number= 0;
  592.  
  593.         fprintf(gOutfile, "LightSource \"pointlight\" %d"
  594.             " \"from\" [ %#g %#g %#g ] \"intensity\" [20]\n", number++,
  595.             vec[X], vec[Y], vec[Z]);
  596.       }
  597.         break;
  598.     }
  599. }
  600.  
  601. /*-----------------------------------------------------------------*/
  602. /*
  603.  * Output background color.  A color is simply RGB (monitor dependent, but
  604.  * that's life).
  605.  */
  606. void
  607. lib_output_background_color(color)
  608.     COORD3 color;
  609. {
  610.     switch (gRT_out_format) {
  611.     case OUTPUT_VIDEO:
  612.     case OUTPUT_DELAYED:
  613.     case OUTPUT_PLG:
  614.     case OUTPUT_OBJ:
  615.     case OUTPUT_RWX:
  616.         COPY_COORD3(gBkgnd_color, color);
  617.         break;
  618.  
  619.     case OUTPUT_NFF:
  620.         fprintf(gOutfile, "b %g %g %g\n", color[X], color[Y], color[Z]);
  621.         break;
  622.  
  623.     case OUTPUT_POVRAY_10:
  624.         /* POV-Ray 1.0 does not support a background color */
  625.         /* Instead, create arbitrarily large enclosing sphere of that
  626.          * color */
  627.         tab_indent();
  628.         fprintf(gOutfile, "// background color:\n");
  629.  
  630.         tab_indent();
  631.         fprintf(gOutfile, "object {\n");
  632.         tab_inc();
  633.  
  634.         tab_indent();
  635.         fprintf(gOutfile, "sphere { <0 0 0> 9000  ");
  636.         fprintf(gOutfile,
  637.         "texture { ambient 1 diffuse 0 color red %g green %g blue %g } }\n",
  638.                color[X], color[Y], color[Z]);
  639.         tab_dec();
  640.         tab_indent();
  641.         fprintf(gOutfile, "} // object - background\n");
  642.         fprintf(gOutfile, "\n");
  643.         break;
  644.  
  645.     case OUTPUT_POVRAY_20:
  646.         tab_indent();
  647.         fprintf(gOutfile, "background { color red %g green %g blue %g }\n",
  648.            color[X], color[Y], color[Z]);
  649.         fprintf(gOutfile, "\n");
  650.         break;
  651.  
  652.     case OUTPUT_POLYRAY:
  653.         tab_indent();
  654.         fprintf(gOutfile, "background <%g, %g, %g>\n",
  655.             color[X], color[Y], color[Z]);
  656.         fprintf(gOutfile, "\n");
  657.         break;
  658.  
  659.     case OUTPUT_VIVID:
  660.         /* Vivid insists on putting the background into the studio */
  661.         tab_indent();
  662.         fprintf(gOutfile, "studio { background %g %g %g }\n",
  663.             color[X], color[Y], color[Z]);
  664.         fprintf(gOutfile, "\n");
  665.         break;
  666.  
  667.     case OUTPUT_QRT:
  668.         tab_indent();
  669.         fprintf(gOutfile, "SKY ( horiz = (%g,%g,%g), zenith = (%g,%g,%g),",
  670.             color[X], color[Y], color[Z],
  671.             color[X], color[Y], color[Z]);
  672.         fprintf(gOutfile, " dither = 0 )\n");
  673.         break;
  674.  
  675.     case OUTPUT_RAYSHADE:
  676.         fprintf(gOutfile, "background %g %g %g\n",
  677.             color[X], color[Y], color[Z]);
  678.         break;
  679.  
  680.     case OUTPUT_RTRACE:
  681.         fprintf(gOutfile, "Colors\n");
  682.         fprintf(gOutfile, "%g %g %g\n", color[X], color[Y], color[Z]);
  683.         fprintf(gOutfile, "0 0 0\n");
  684.         break;
  685.  
  686.     case OUTPUT_RAWTRI:
  687.     case OUTPUT_DXF:
  688.         break;
  689.  
  690.     case OUTPUT_ART:
  691.         tab_indent();
  692.         fprintf(gOutfile, "background %g, %g, %g\n",
  693.             color[X], color[Y], color[Z]);
  694.         fprintf(gOutfile, "\n");
  695.         break;
  696.       case OUTPUT_RIB:
  697.         fprintf(gOutfile, "# Background color [%#g %#g %#g]\n",
  698.             color[X], color[Y], color[Z]);
  699.         break;
  700.  
  701.     }
  702. }
  703.  
  704. /*-----------------------------------------------------------------*/
  705. static char *
  706. create_surface_name(name, val)
  707.     char *name;
  708.     int val;
  709. {
  710.     char *txname;
  711.  
  712.     if (name != NULL)
  713.     return name;
  714.  
  715.     txname = (char *)malloc(7*sizeof(char));
  716.     if (txname == NULL)
  717.     return NULL;
  718.     sprintf(txname, "txt%03d", val);
  719.     txname[6] = '\0';
  720.     return txname;
  721. }
  722.  
  723. /*-----------------------------------------------------------------*/
  724. /*
  725.  * Output color and shading parameters for all following objects
  726.  *
  727.  * For POV-Ray and Polyray, a character string will be returned that
  728.  * identified this texture.  The default texture will be updated with
  729.  * the name generated by this function.
  730.  *
  731.  * Meaning of the color and shading parameters:
  732.  *    name   = name that this surface can be referenced by...
  733.  *    color  = surface color
  734.  *    ka     = ambient component
  735.  *    kd     = diffuse component
  736.  *    ks     = amount contributed from the reflected direction
  737.  *    shine  = contribution from specular highlights
  738.  *    ang    = angle at which the specular highlight falls to 50% of maximum
  739.  *    t      = amount from the refracted direction
  740.  *    i_of_r = index of refraction of the surface
  741.  *
  742.  */
  743. char *
  744. lib_output_color(name, color, ka, kd, ks, shine, ang, kt, i_of_r)
  745.     char *name;
  746.     COORD3 color;
  747.     double ka, kd, ks, shine, ang, kt, i_of_r;
  748. {
  749.     surface_ptr new_surf;
  750.     char *txname = NULL;
  751.     double phong_pow;
  752.  
  753.     /* Increment the number of surface types we know about */
  754.     ++gTexture_count;
  755.     gTexture_ior = i_of_r;
  756.  
  757.     /* Calculate the Phong coefficient */
  758.     phong_pow = PI * ang / 180.0;
  759.     if (phong_pow <= 0.0)
  760.     phong_pow = 100000.0;
  761.     else if (phong_pow >= (PI/4.0))
  762.     phong_pow = 0.000001;
  763.     else
  764.     phong_pow = -(log(2.0) / log(cos(2.0 * phong_pow)));
  765.  
  766.     switch (gRT_out_format) {
  767.     case OUTPUT_DELAYED:
  768.         new_surf = (surface_ptr)malloc(sizeof(struct surface_struct));
  769.         if (new_surf == NULL)
  770.            /* Quietly fail */
  771.         return NULL;
  772.         new_surf->surf_name = create_surface_name(name, gTexture_count);
  773.         new_surf->surf_index = gTexture_count;
  774.         COPY_COORD3(new_surf->color, color);
  775.         new_surf->ka = ka;
  776.         new_surf->kd = kd;
  777.         new_surf->ks = ks;
  778.         new_surf->shine = shine;
  779.         new_surf->ang = ang;
  780.         new_surf->kt = kt;
  781.         new_surf->ior = i_of_r;
  782.         new_surf->next = gLib_surfaces;
  783.         gLib_surfaces = new_surf;
  784.         break;
  785.  
  786.     case OUTPUT_PLG:
  787.     case OUTPUT_VIDEO:
  788.         COPY_COORD3(gFgnd_color, color);
  789.         break;
  790.  
  791.     case OUTPUT_NFF:
  792.         fprintf(gOutfile, "f %g %g %g %g %g %g %g %g\n",
  793.         color[X], color[Y], color[Z], kd, ks, phong_pow, kt, i_of_r);
  794.         break;
  795.  
  796.     case OUTPUT_POVRAY_10:
  797.         txname = create_surface_name(name, gTexture_count);
  798.         tab_indent();
  799.         fprintf(gOutfile, "#declare %s = texture {\n", txname);
  800.         tab_inc();
  801.  
  802.         tab_indent();
  803.         fprintf(gOutfile, "color red %g green %g blue %g",
  804.             color[X], color[Y], color[Z]);
  805.         if (kt > 0)
  806.         fprintf(gOutfile, " alpha %g", kt);
  807.         fprintf(gOutfile, "\n");
  808.  
  809.         tab_indent();
  810.         fprintf(gOutfile, "ambient %g\n", ka);
  811.  
  812.         tab_indent();
  813.         fprintf(gOutfile, "diffuse %g\n", kd);
  814.  
  815.         if (shine != 0) {
  816.         tab_indent();
  817.         fprintf(gOutfile, "phong %g phong_size %g\n", shine, phong_pow);
  818.         }
  819.  
  820.         if (ks != 0) {
  821.         tab_indent();
  822.         fprintf(gOutfile, "reflection %g\n", ks);
  823.         }
  824.  
  825.         if (kt != 0) {
  826.         tab_indent();
  827.         fprintf(gOutfile, "refraction 1.0 ior %g\n", i_of_r);
  828.         }
  829.  
  830.         tab_dec();
  831.         tab_indent();
  832.         fprintf(gOutfile, "} // texture %s\n", txname);
  833.         fprintf(gOutfile, "\n");
  834.         break;
  835.  
  836.     case OUTPUT_POVRAY_20:
  837.         txname = create_surface_name(name, gTexture_count);
  838.         tab_indent();
  839.         fprintf(gOutfile, "#declare %s = texture {\n", txname);
  840.         tab_inc();
  841.  
  842.         tab_indent();
  843.         fprintf(gOutfile, "pigment {\n");
  844.         tab_inc();
  845.  
  846.         tab_indent();
  847.         fprintf(gOutfile, "color red %g green %g blue %g",
  848.             color[X], color[Y], color[Z]);
  849.         if (kt > 0)
  850.         fprintf(gOutfile, " filter %g", kt);
  851.         fprintf(gOutfile, "\n");
  852.  
  853.         tab_dec();
  854.         tab_indent();
  855.         fprintf(gOutfile, "} // pigment\n");
  856.  
  857.         tab_indent();
  858.         fprintf(gOutfile, "// normal { bumps, ripples, etc. }\n");
  859.  
  860.         tab_indent();
  861.         fprintf(gOutfile, "finish {\n");
  862.         tab_inc();
  863.  
  864.         tab_indent();
  865.         fprintf(gOutfile, "ambient %g\n", ka);
  866.  
  867.         tab_indent();
  868.         fprintf(gOutfile, "diffuse %g\n", kd);
  869.  
  870.         if (shine != 0) {
  871.         tab_indent();
  872.         fprintf(gOutfile, "phong %g  phong_size %g\n", shine, phong_pow);
  873.         }
  874.  
  875.         if (ks != 0) {
  876.         tab_indent();
  877.         fprintf(gOutfile, "reflection %g\n", ks);
  878.         }
  879.  
  880.         if (kt != 0) {
  881.         tab_indent();
  882.         fprintf(gOutfile, "refraction 1.0 ior %g\n", i_of_r);
  883.         }
  884.  
  885.         tab_dec();
  886.         tab_indent();
  887.         fprintf(gOutfile, "} // finish\n");
  888.  
  889.         tab_dec();
  890.         tab_indent();
  891.         fprintf(gOutfile, "} // texture %s\n", txname);
  892.         fprintf(gOutfile, "\n");
  893.         break;
  894.  
  895.     case OUTPUT_POLYRAY:
  896.         txname = create_surface_name(name, gTexture_count);
  897.         tab_indent();
  898.         fprintf(gOutfile, "define %s\n", txname);
  899.  
  900.         tab_indent();
  901.         fprintf(gOutfile, "texture {\n");
  902.         tab_inc();
  903.  
  904.         tab_indent();
  905.         fprintf(gOutfile, "surface {\n");
  906.         tab_inc();
  907.  
  908.         tab_indent();
  909.         fprintf(gOutfile, "ambient <%g, %g, %g>, %g\n",
  910.            color[X], color[Y], color[Z], ka);
  911.  
  912.         tab_indent();
  913.         fprintf(gOutfile, "diffuse <%g, %g, %g>, %g\n",
  914.            color[X], color[Y], color[Z], kd);
  915.  
  916.         if (shine != 0) {
  917.         tab_indent();
  918.         fprintf(gOutfile, "specular white, %g\n", shine);
  919.         tab_indent();
  920.         fprintf(gOutfile, "microfacet Phong %g\n", ang);
  921.         }
  922.  
  923.         if (ks != 0) {
  924.         tab_indent();
  925.         fprintf(gOutfile, "reflection white, %g\n", ks);
  926.         }
  927.  
  928.         if (kt != 0) {
  929.         tab_indent();
  930.         fprintf(gOutfile, "transmission white, %g, %g\n", kt, i_of_r);
  931.         }
  932.  
  933.         tab_dec();
  934.         tab_indent();
  935.         fprintf(gOutfile, "}\n");
  936.  
  937.         tab_dec();
  938.         tab_indent();
  939.         fprintf(gOutfile, "}\n");
  940.         fprintf(gOutfile, "\n");
  941.         break;
  942.  
  943.     case OUTPUT_VIVID:
  944.         tab_indent();
  945.         fprintf(gOutfile, "surface {\n");
  946.         tab_inc();
  947.  
  948.         tab_indent();
  949.         fprintf(gOutfile, "ambient %g %g %g\n",
  950.             ka * color[X], ka * color[Y], ka * color[Z], ka);
  951.  
  952.         tab_indent();
  953.         fprintf(gOutfile, "diffuse %g %g %g\n",
  954.             kd * color[X], kd * color[Y], kd * color[Z], ka);
  955.  
  956.         if (shine != 0) {
  957.         tab_indent();
  958.         fprintf(gOutfile, "shine %g %g %g %g\n",
  959.                phong_pow, shine, shine, shine);
  960.         }
  961.         if (ks != 0) {
  962.         tab_indent();
  963.         fprintf(gOutfile, "specular %g %g %g\n", ks, ks, ks);
  964.         }
  965.         if (kt != 0) {
  966.         tab_indent();
  967.         fprintf(gOutfile, "transparent %g %g %g\n",
  968.              kt * color[X], kt * color[Y], kt * color[Z]);
  969.         tab_indent();
  970.         fprintf(gOutfile, "ior %g\n", i_of_r);
  971.         }
  972.  
  973.         tab_dec();
  974.         tab_indent();
  975.         fprintf(gOutfile, "}\n");
  976.         fprintf(gOutfile, "\n");
  977.         break;
  978.  
  979.     case OUTPUT_QRT:
  980.         tab_indent();
  981.         fprintf(gOutfile, "DEFAULT (\n");
  982.         tab_inc();
  983.  
  984.         tab_indent();
  985.         fprintf(gOutfile, "amb = (%g,%g,%g),\n",
  986.             ka * color[X], ka * color[Y], ka * color[Z], ka);
  987.         tab_indent();
  988.         fprintf(gOutfile, "diff = (%g,%g,%g),\n",
  989.             kd * color[X], kd * color[Y], kd * color[Z], ka);
  990.         tab_indent();
  991.         fprintf(gOutfile, "reflect = %g, sreflect = %g,\n",
  992.             shine, phong_pow);
  993.         tab_indent();
  994.         fprintf(gOutfile, "mirror = (%g,%g,%g),\n",
  995.             ks * color[X], ks * color[Y], ks * color[Z]);
  996.         tab_indent();
  997.         fprintf(gOutfile, "trans = (%g,%g,%g), index = %g,\n",
  998.             kt * color[X], kt * color[Y], kt * color[Z], i_of_r);
  999.         tab_indent();
  1000.         fprintf(gOutfile, "dither = 0\n");
  1001.  
  1002.         tab_dec();
  1003.         tab_indent();
  1004.         fprintf(gOutfile, ")\n");
  1005.         fprintf(gOutfile, "\n");
  1006.         break;
  1007.  
  1008.     case OUTPUT_RAYSHADE:
  1009.         txname = create_surface_name(name, gTexture_count);
  1010.         tab_indent();
  1011.         fprintf(gOutfile, "surface %s\n", txname);
  1012.         tab_inc();
  1013.  
  1014.         tab_indent();
  1015.         fprintf(gOutfile, "ambient %g %g %g\n",
  1016.            ka * color[X], ka * color[Y], ka * color[Z]);
  1017.         tab_indent();
  1018.         fprintf(gOutfile, "diffuse %g %g %g\n",
  1019.            kd * color[X], kd * color[Y], kd * color[Z]);
  1020.  
  1021.         if (shine != 0) {
  1022.         tab_indent();
  1023.         fprintf(gOutfile, "specular %g %g %g\n", shine, shine, shine);
  1024.         tab_indent();
  1025.         fprintf(gOutfile, "specpow %g\n", phong_pow);
  1026.         }
  1027.  
  1028.         if (ks != 0) {
  1029.         if (shine == 0.0) {
  1030.             /* If there is no Phong highlighting, but there is
  1031.                reflectivity, then we need to define the color of
  1032.                specular reflections */
  1033.             tab_indent();
  1034.             fprintf(gOutfile, "specular 1.0 1.0 1.0\n");
  1035.             tab_indent();
  1036.             fprintf(gOutfile, "specpow 0.0\n");
  1037.         }
  1038.         tab_indent();
  1039.         fprintf(gOutfile, "reflect %g\n", ks);
  1040.         }
  1041.  
  1042.         if (kt != 0) {
  1043.         tab_indent();
  1044.         fprintf(gOutfile, "transp %g index %g\n", kt, i_of_r);
  1045.         }
  1046.  
  1047.         tab_dec();
  1048.         tab_indent();
  1049.         break;
  1050.  
  1051.     case OUTPUT_RTRACE:
  1052.         if (shine > 0 && ks == 0.0) ks = shine;
  1053.         fprintf(gOutfile, "1 %g %g %g %g %g %g %g %g %g %g 0 %g %g %g\n",
  1054.             color[X], color[Y], color[Z],
  1055.             kd, kd, kd,
  1056.             ks, ks, ks,
  1057.             (phong_pow > 100.0 ? 100.0 : phong_pow),
  1058.             kt, kt, kt);
  1059.         break;
  1060.  
  1061.     case OUTPUT_OBJ:
  1062.         txname = create_surface_name(name, gTexture_count);
  1063.         fprintf(gOutfile, "usemtl %s\n", txname);
  1064.         break;
  1065.  
  1066.     case OUTPUT_RWX:
  1067.         tab_indent();
  1068.         fprintf(gOutfile, "Color %g %g %g\n",
  1069.             color[X], color[Y], color[Z]);
  1070.         tab_indent();
  1071.         fprintf(gOutfile, "Surface %g %g %g\n",
  1072.             ka, kd, ks);
  1073.         tab_indent();
  1074.         fprintf(gOutfile, "Opacity %g\n",
  1075.             1.0-kt);
  1076.        break;
  1077.  
  1078.     case OUTPUT_RAWTRI:
  1079.         txname = create_surface_name(name, gTexture_count);
  1080.         break;
  1081.  
  1082.     case OUTPUT_ART:
  1083.         tab_indent();
  1084.         fprintf(gOutfile, "colour %g, %g, %g\n",
  1085.             color[X], color[Y], color[Z]);
  1086.         tab_indent();
  1087.         fprintf(gOutfile, "ambient %g, %g, %g\n",
  1088.             color[X] * 0.05, color[Y] * 0.05, color[Z] * 0.05);
  1089.  
  1090.         if (ks != 0.0) {
  1091.         tab_indent();
  1092.         fprintf(gOutfile, "material %g, %g, %g, %g\n",
  1093.                 i_of_r, kd, ks, phong_pow);
  1094.         } else {
  1095.         tab_indent();
  1096.         fprintf(gOutfile, "material %g, %g, 0.0, 0.0\n",
  1097.                 i_of_r, kd);
  1098.         }
  1099.  
  1100.         tab_indent();
  1101.         fprintf(gOutfile, "reflectance %g\n", ks);
  1102.         tab_indent();
  1103.         fprintf(gOutfile, "transparency %g\n", kt);
  1104.         fprintf(gOutfile, "\n");
  1105.         break;
  1106.       case OUTPUT_RIB:
  1107.         fprintf(gOutfile, "\n");
  1108.         if (name != NULL)
  1109.           fprintf(gOutfile, "Attribute \"identifier\" \"name\" \"%s\"\n",
  1110.               name);
  1111.         fprintf(gOutfile, "Color [ %#g %#g %#g ]\n",
  1112.             color[X], color[Y], color[Z]);
  1113.         fprintf(gOutfile, "Surface \"plastic\" \"Ka\" %#g \"Kd\" %#g"
  1114.             " \"Ks\" %#g \"roughness\" %#g \n",
  1115.             ka, kd, shine, 1.0/phong_pow);
  1116.         break;
  1117.       case OUTPUT_DXF:
  1118.         break;
  1119.       }
  1120.  
  1121.     /* Stash away the current texture name */
  1122.     gTexture_name = txname;
  1123.  
  1124.     return txname;
  1125. }
  1126.