home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Graphics / SPD / Sources / libpr2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  26.3 KB  |  936 lines  |  [TEXT/R*ch]

  1. /*
  2.  * libpr2.c - a library of primitive object output routines, part 2 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. /*
  28.  * Output cylinder or cone.  A cylinder is defined as having a radius and an
  29.  * axis defined by two points, which also define the top and bottom edge of the
  30.  * cylinder.  A cone is defined similarly, the difference being that the apex
  31.  * and base radii are different.  The apex radius is defined as being smaller
  32.  * than the base radius.  Note that the surface exists without endcaps.
  33.  *
  34.  * If gRT_out_format=OUTPUT_CURVES, output the cylinder/cone in format:
  35.  *     "c"
  36.  *     base.x base.y base.z base_radius
  37.  *     apex.x apex.y apex.z apex_radius
  38.  *
  39.  * If the format=OUTPUT_POLYGONS, the surface is polygonalized and output.
  40.  * (4*OUTPUT_RESOLUTION) polygons are output as rectangles by
  41.  * lib_output_polypatch.
  42.  */
  43. void
  44. lib_output_cylcone(base_pt, apex_pt, curve_format)
  45.     COORD4 base_pt, apex_pt;
  46.     int curve_format;
  47. {
  48.     object_ptr new_object;
  49.     COORD4  axis;
  50.     double  len, cottheta, xang, yang, height;
  51.  
  52.     if (gRT_out_format == OUTPUT_DELAYED) {
  53.     /* Save all the pertinent information */
  54.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  55.     if (new_object == NULL)
  56.        /* Quietly fail */
  57.        return;
  58.     new_object->object_type  = CONE_OBJ;
  59.     new_object->curve_format = curve_format;
  60.     new_object->surf_index   = gTexture_count;
  61.     COPY_COORD4(new_object->object_data.cone.apex_pt, apex_pt);
  62.     COPY_COORD4(new_object->object_data.cone.base_pt, base_pt);
  63.     new_object->next_object = gLib_objects;
  64.     gLib_objects = new_object;
  65.  
  66.     } else if (curve_format == OUTPUT_CURVES) {
  67.     switch (gRT_out_format) {
  68.         case OUTPUT_VIDEO:
  69.         case OUTPUT_PLG:
  70.         lib_output_polygon_cylcone(base_pt, apex_pt);
  71.         break;
  72.  
  73.         case OUTPUT_NFF:
  74.         fprintf(gOutfile, "c\n" ) ;
  75.         fprintf(gOutfile, "%g %g %g %g\n",
  76.             base_pt[X], base_pt[Y], base_pt[Z], base_pt[W]);
  77.         fprintf(gOutfile, "%g %g %g %g\n",
  78.             apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W]);
  79.         break;
  80.  
  81.         case OUTPUT_POVRAY_10:
  82.         /*
  83.         Since POV-Ray uses infinite primitives, we will start
  84.         with a cone aligned with the z-axis (QCone_Z) and figure
  85.         out how to clip and scale it to match what we want
  86.         */
  87.         if (apex_pt[W] < base_pt[W]) {
  88.             /* Put the bigger end at the top */
  89.             COPY_COORD4(axis, base_pt);
  90.             COPY_COORD4(base_pt, apex_pt);
  91.             COPY_COORD4(apex_pt, axis);
  92.             }
  93.         /* Find the axis and axis length */
  94.         SUB3_COORD3(axis, apex_pt, base_pt);
  95.         len = lib_normalize_vector(axis);
  96.         if (len < EPSILON) {
  97.            /* Degenerate cone/cylinder */
  98.            fprintf(gOutfile, "// degenerate cone/cylinder!  Ignored...\n");
  99.            break;
  100.            }
  101.         if (ABSOLUTE(apex_pt[W] - base_pt[W]) < EPSILON) {
  102.            /* Treat this thing as a cylinder */
  103.            cottheta = len;
  104.            tab_indent();
  105.            fprintf(gOutfile, "object {\n");
  106.            tab_inc();
  107.  
  108.            tab_indent();
  109.            fprintf(gOutfile, "quadric { <1 1 0> <0 0 0> <0 0 0> -1 } // cylinder\n");
  110.  
  111.            tab_indent();
  112.            fprintf(gOutfile, "clipped_by {\n");
  113.            tab_inc();
  114.  
  115.            tab_indent();
  116.            fprintf(gOutfile, "intersection {\n");
  117.            tab_inc();
  118.  
  119.            tab_indent();
  120.            fprintf(gOutfile, "plane { <0 0 -1> 0 }\n");
  121.            tab_indent();
  122.            fprintf(gOutfile, "plane { <0 0  1> 1 }\n");
  123.  
  124.            tab_dec();
  125.            tab_indent();
  126.            fprintf(gOutfile, "} // intersection\n");
  127.  
  128.            tab_dec();
  129.            tab_indent();
  130.            fprintf(gOutfile, "} // clip\n");
  131.  
  132.            tab_indent();
  133.            fprintf(gOutfile, "scale <%g %g 1>\n", base_pt[W], base_pt[W]);
  134.            }
  135.         else {
  136.            /* Determine alignment */
  137.            cottheta = len / (apex_pt[W] - base_pt[W]);
  138.            tab_indent();
  139.            fprintf(gOutfile, "object {\n");
  140.            tab_inc();
  141.  
  142.            tab_indent();
  143.            fprintf(gOutfile, "quadric{ <1 1 -1> <0 0 0> <0 0 0> 0 } // cone\n");
  144.  
  145.            tab_indent();
  146.            fprintf(gOutfile, "clipped_by {\n");
  147.            tab_inc();
  148.  
  149.            tab_indent();
  150.            fprintf(gOutfile, "intersection {\n");
  151.            tab_inc();
  152.  
  153.            tab_indent();
  154.            fprintf(gOutfile, "plane { <0 0 -1> %g}\n", -base_pt[W]);
  155.            tab_indent();
  156.            fprintf(gOutfile, "plane { <0 0  1> %g}\n", apex_pt[W]);
  157.  
  158.            tab_dec();
  159.            tab_indent();
  160.            fprintf(gOutfile, "} // intersection\n");
  161.  
  162.            tab_dec();
  163.            tab_indent();
  164.            fprintf(gOutfile, "} // clip\n");
  165.  
  166.            tab_indent();
  167.            fprintf(gOutfile, "translate <0 0 %g>\n", -base_pt[W]);
  168.            }
  169.  
  170.         tab_indent();
  171.         fprintf(gOutfile, "scale <1 1 %g>\n", cottheta);
  172.  
  173.         len = sqrt(axis[X] * axis[X] + axis[Z] * axis[Z]);
  174.         xang = -180.0 * asin(axis[Y]) / PI;
  175.         if (len < EPSILON)
  176.           yang = 0.0;
  177.         else
  178.           yang = 180.0 * acos(axis[Z] / len) / PI;
  179.         if (axis[X] < 0)
  180.            yang = -yang;
  181.         tab_indent();
  182.         fprintf(gOutfile, "rotate <%g %g 0>\n", xang, yang);
  183.         tab_indent();
  184.         fprintf(gOutfile, "translate <%g %g %g>\n",
  185.             base_pt[X], base_pt[Y], base_pt[Z]);
  186.         if (gTexture_name != NULL) {
  187.            tab_indent();
  188.            fprintf(gOutfile, "texture { %s }\n", gTexture_name);
  189.            }
  190.  
  191.         tab_dec();
  192.         tab_indent();
  193.         fprintf(gOutfile, "} // object\n");
  194.         fprintf(gOutfile, "\n");
  195.         break;
  196.  
  197.         case OUTPUT_POVRAY_20:
  198.         /* of course if apex_pt[W] ~= base_pt[W], could do cylinder */
  199.         tab_indent();
  200.         fprintf(gOutfile, "cone {\n");
  201.         tab_inc();
  202.  
  203.         tab_indent();
  204.         fprintf(gOutfile, "<%g, %g, %g>, %g,\n",
  205.             apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W]);
  206.         tab_indent();
  207.         fprintf(gOutfile, "<%g, %g, %g>, %g open\n",
  208.             base_pt[X], base_pt[Y], base_pt[Z], base_pt[W]);
  209.         if (gTexture_name != NULL) {
  210.            tab_indent();
  211.            fprintf(gOutfile, "texture { %s }\n", gTexture_name);
  212.            }
  213.  
  214.         tab_dec();
  215.         tab_indent();
  216.         fprintf(gOutfile, "}\n");
  217.         fprintf(gOutfile, "\n");
  218.         break;
  219.  
  220.         case OUTPUT_POLYRAY:
  221.         tab_indent();
  222.         fprintf(gOutfile, "object {");
  223.         tab_inc();
  224.  
  225.         tab_indent();
  226.         if (base_pt[W] == apex_pt[W])
  227.            fprintf(gOutfile, "cylinder <%g, %g, %g>, <%g, %g, %g>, %g",
  228.               base_pt[X], base_pt[Y], base_pt[Z],
  229.               apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W]);
  230.         else
  231.            fprintf(gOutfile, "cone <%g, %g, %g>, %g, <%g, %g, %g>, %g",
  232.               base_pt[X], base_pt[Y], base_pt[Z], base_pt[W],
  233.               apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W]);
  234.         if (gTexture_name != NULL)
  235.            fprintf(gOutfile, " %s", gTexture_name);
  236.         fprintf(gOutfile, "\n");
  237.  
  238.         tab_dec();
  239.         tab_indent();
  240.         fprintf(gOutfile, "}\n");
  241.         fprintf(gOutfile, "\n");
  242.         break;
  243.  
  244.         case OUTPUT_VIVID:
  245.         tab_indent();
  246.         fprintf(gOutfile, "cone {");
  247.         tab_inc();
  248.  
  249.         tab_indent();
  250.         fprintf(gOutfile, " base %g %g %g base_radius %g\n",
  251.             base_pt[X], base_pt[Y], base_pt[Z], base_pt[W]);
  252.         tab_indent();
  253.         fprintf(gOutfile, " apex %g %g %g apex_radius %g\n",
  254.             apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W]);
  255.  
  256.         tab_dec();
  257.         tab_indent();
  258.         fprintf(gOutfile, "}\n");
  259.         fprintf(gOutfile, "\n");
  260.         break;
  261.  
  262.         case OUTPUT_QRT:
  263.         fprintf(gOutfile, "BEGIN_BBOX\n");
  264.         lib_output_polygon_cylcone(base_pt, apex_pt);
  265.         fprintf(gOutfile, "END_BBOX\n");
  266.         break;
  267.  
  268.         case OUTPUT_RAYSHADE:
  269.         fprintf(gOutfile, "cone ");
  270.         if (gTexture_name != NULL)
  271.             fprintf(gOutfile, "%s ", gTexture_name);
  272.         fprintf(gOutfile, " %g %g %g %g %g %g %g %g\n",
  273.             base_pt[W], base_pt[X], base_pt[Y], base_pt[Z],
  274.             apex_pt[W], apex_pt[X], apex_pt[Y], apex_pt[Z]);
  275.         break;
  276.  
  277.         case OUTPUT_RTRACE:
  278.         fprintf(gOutfile, "4 %d %g %g %g %g %g %g %g %g %g\n",
  279.             gTexture_count, gTexture_ior,
  280.             base_pt[X], base_pt[Y], base_pt[Z], base_pt[W],
  281.             apex_pt[X], apex_pt[Y], apex_pt[Z], apex_pt[W]);
  282.         break;
  283.  
  284.         case OUTPUT_ART:
  285.         if (base_pt[W] != apex_pt[W]) {
  286.             tab_indent();
  287.             fprintf(gOutfile, "cone {\n");
  288.             tab_inc();
  289.             tab_indent();
  290.             fprintf(gOutfile, "radius %g  center(%g, %g, %g)\n",
  291.                 base_pt[W], base_pt[X], base_pt[Y], base_pt[Z]);
  292.             tab_indent();
  293.             fprintf(gOutfile, "radius %g  center(%g, %g, %g)\n",
  294.                 apex_pt[W], apex_pt[X], apex_pt[Y], apex_pt[Z]);
  295.         } else {
  296.             tab_indent();
  297.             fprintf(gOutfile, "cylinder {\n");
  298.             tab_inc();
  299.             tab_indent();
  300.             fprintf(gOutfile, "radius %g  center(%g, %g, %g)\n",
  301.                 base_pt[W], base_pt[X], base_pt[Y], base_pt[Z]);
  302.             tab_indent();
  303.             fprintf(gOutfile, "center(%g, %g, %g)\n",
  304.                 apex_pt[X], apex_pt[Y], apex_pt[Z]);
  305.         }
  306.  
  307.         tab_dec();
  308.         tab_indent();
  309.         fprintf(gOutfile, "}\n");
  310.         fprintf(gOutfile, "\n");
  311.         break;
  312.  
  313.         case OUTPUT_RAWTRI:
  314.         case OUTPUT_DXF:
  315.         lib_output_polygon_cylcone(base_pt, apex_pt);
  316.         break;
  317.  
  318.         case OUTPUT_RIB:
  319.         /* translate and orient */
  320.         tab_indent();
  321.         fprintf(gOutfile, "TransformBegin\n");
  322.         tab_inc();
  323.  
  324.         SUB3_COORD3(axis, apex_pt, base_pt);
  325.         height= len = lib_normalize_vector(axis);
  326.         if (len < EPSILON)
  327.         {
  328.           /* Degenerate cone/cylinder */
  329.           fprintf(gOutfile, "# degenerate cone/cylinder!\n"
  330.               "Ignored...\n");
  331.           break;
  332.         }
  333.  
  334.         axis_to_z(axis, &xang, &yang);
  335.  
  336.         /* Calculate transformation from intrisic position */
  337.         tab_indent();
  338.         fprintf(gOutfile, "Translate %#g %#g %#g\n",
  339.             base_pt[X], base_pt[Y], base_pt[Z]);
  340.         tab_indent();
  341.         fprintf(gOutfile, "Rotate %#g 0 1 0\n", yang);  /* was -yang */
  342.         tab_indent();
  343.         fprintf(gOutfile, "Rotate %#g 1 0 0\n", xang);  /* was -xang */
  344.         if (ABSOLUTE(apex_pt[W] - base_pt[W]) < EPSILON)
  345.         {
  346.           /* Treat this thing as a cylinder */
  347.           tab_indent();
  348.           fprintf(gOutfile, "Cylinder [ %#g %#g %#g %#g ]\n",
  349.               apex_pt[W], 0.0, len, 360.0);
  350.         }
  351.         else
  352.         {
  353.           /* We use a hyperboloid, because a cone cannot be cut
  354.            * at the top */
  355.           tab_indent();
  356.           fprintf(gOutfile, "Hyperboloid %#g 0 0  %#g 0 %#g  360.0\n",
  357.               base_pt[W], apex_pt[W], height);
  358.         }
  359.  
  360.         tab_dec();
  361.         tab_indent();
  362.         fprintf(gOutfile, "TransformEnd\n");
  363.         break;
  364.           }
  365.     }
  366.     else
  367.       lib_output_polygon_cylcone(base_pt, apex_pt);
  368. }
  369.  
  370.  
  371. /*-----------------------------------------------------------------*/
  372. void
  373. lib_output_disc(center, normal, iradius, oradius, curve_format)
  374.     COORD3 center, normal;
  375.     double iradius, oradius;
  376.     int curve_format;
  377. {
  378.     object_ptr new_object;
  379.     COORD4  axis, base, apex;
  380.     COORD3  axis_rib ;
  381.     double  len, xang, yang;
  382.  
  383.     if (gRT_out_format == OUTPUT_DELAYED) {
  384.     /* Save all the pertinent information */
  385.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  386.     if (new_object == NULL)
  387.         /* Quietly fail */
  388.         return;
  389.     new_object->object_type  = DISC_OBJ;
  390.     new_object->curve_format = curve_format;
  391.     new_object->surf_index   = gTexture_count;
  392.     COPY_COORD4(new_object->object_data.disc.center, center);
  393.     COPY_COORD4(new_object->object_data.disc.normal, normal);
  394.     new_object->object_data.disc.iradius = iradius;
  395.     new_object->object_data.disc.iradius = oradius;
  396.     new_object->next_object = gLib_objects;
  397.     gLib_objects = new_object;
  398.     } else if (curve_format == OUTPUT_CURVES) {
  399.     switch (gRT_out_format) {
  400.         case OUTPUT_VIDEO:
  401.         case OUTPUT_NFF:
  402.         case OUTPUT_PLG:
  403.         case OUTPUT_VIVID:
  404.         case OUTPUT_RAYSHADE:
  405.         case OUTPUT_RAWTRI:
  406.         case OUTPUT_DXF:
  407.         lib_output_polygon_disc(center, normal, iradius, oradius);
  408.         break;
  409.  
  410.         case OUTPUT_POVRAY_10:
  411.         /* A disc is a plane intersected with either one or two
  412.          * spheres
  413.          */
  414.         COPY_COORD3(axis, normal);
  415.         len = lib_normalize_vector(axis);
  416.         tab_indent();
  417.         fprintf(gOutfile, "object {\n");
  418.         tab_inc();
  419.  
  420.         tab_indent();
  421.         fprintf(gOutfile, "plane { <0 0 1> 1 }\n");
  422.  
  423.         tab_indent();
  424.         fprintf(gOutfile, "clipped_by {\n");
  425.         tab_inc();
  426.  
  427.         if (iradius > 0.0) {
  428.             tab_indent();
  429.             fprintf(gOutfile, "intersection {\n");
  430.             tab_inc();
  431.  
  432.             tab_indent();
  433.             fprintf(gOutfile, "sphere { <0 0 0> %g inverse }\n",
  434.                 iradius);
  435.             tab_indent();
  436.             fprintf(gOutfile, "sphere { <0 0 1> %g }\n", oradius);
  437.  
  438.             tab_dec();
  439.             tab_indent();
  440.             fprintf(gOutfile, "} // intersection\n");
  441.         }
  442.         else {
  443.             tab_indent();
  444.             fprintf(gOutfile, "object { sphere { <0 0 0> %g } }\n",
  445.                 oradius);
  446.         }
  447.  
  448.         tab_dec();
  449.         tab_indent();
  450.         fprintf(gOutfile, "} // clip\n");
  451.  
  452.         len = sqrt(axis[X] * axis[X] + axis[Z] * axis[Z]);
  453.         xang = -180.0 * asin(axis[Y]) / PI;
  454.         yang = 180.0 * acos(axis[Z] / len) / PI;
  455.         if (axis[X] < 0)
  456.             yang = -yang;
  457.         tab_indent();
  458.         fprintf(gOutfile, "rotate <%g %g 0>\n", xang, yang);
  459.         tab_indent();
  460.         fprintf(gOutfile, "translate <%g %g %g>\n",
  461.             center[X], center[Y], center[Z]);
  462.  
  463.         if (gTexture_name != NULL) {
  464.             tab_indent();
  465.             fprintf(gOutfile, "texture { %s }", gTexture_name);
  466.         }
  467.  
  468.         tab_dec();
  469.         tab_indent();
  470.         fprintf(gOutfile, "} // object - disc\n");
  471.         fprintf(gOutfile, "\n");
  472.         break;
  473.  
  474.         case OUTPUT_POVRAY_20:
  475.         /* disc <center> <normalVector> radius [holeRadius] */
  476.         tab_indent();
  477.         fprintf(gOutfile, "disc { <%g, %g, %g>",
  478.             center[X], center[Y], center[Z]);
  479.         fprintf(gOutfile, " <%g, %g, %g>",
  480.             normal[X], normal[Y], normal[Z]);
  481.         fprintf(gOutfile, " %g", oradius);
  482.         if (iradius > 0.0)
  483.             fprintf(gOutfile, ", %g", iradius);
  484.         if (gTexture_name != NULL)
  485.             fprintf(gOutfile, " texture { %s }", gTexture_name);
  486.         fprintf(gOutfile, " }\n");
  487.         fprintf(gOutfile, "\n");
  488.         break;
  489.  
  490.         case OUTPUT_POLYRAY:
  491.         tab_indent();
  492.         fprintf(gOutfile, "object { disc <%g, %g, %g>,",
  493.             center[X], center[Y], center[Z]);
  494.         fprintf(gOutfile, " <%g, %g, %g>,",
  495.             normal[X], normal[Y], normal[Z]);
  496.         if (iradius > 0.0)
  497.             fprintf(gOutfile, " %g,", iradius);
  498.         fprintf(gOutfile, " %g", oradius);
  499.         if (gTexture_name != NULL)
  500.             fprintf(gOutfile, " %s", gTexture_name);
  501.         fprintf(gOutfile, " }\n");
  502.         fprintf(gOutfile, "\n");
  503.         break;
  504.  
  505.         case OUTPUT_QRT:
  506.         fprintf(gOutfile, "BEGIN_BBOX\n");
  507.         lib_output_polygon_disc(center, normal, iradius, oradius);
  508.         fprintf(gOutfile, "END_BBOX\n");
  509.         break;
  510.  
  511.         case OUTPUT_RTRACE:
  512.         COPY_COORD3(base, center);
  513.         base[W] = iradius;
  514.         apex[X] = center[X] + normal[X] * EPSILON2;
  515.         apex[Y] = center[Y] + normal[Y] * EPSILON2;
  516.         apex[Z] = center[Z] + normal[Z] * EPSILON2;
  517.         apex[W] = oradius;
  518.         lib_output_cylcone(base, apex, curve_format);
  519.         break;
  520.           case OUTPUT_RIB:
  521.         if (iradius > 0)
  522.         {
  523.           /* translate and orient */
  524.           tab_indent();
  525.           fprintf(gOutfile, "TransformBegin\n");
  526.           tab_inc();
  527.  
  528.           /* Calculate transformation from intrisic position */
  529.           COPY_COORD3(axis_rib, normal);
  530.           len = lib_normalize_vector(axis_rib);
  531.           axis_to_z(axis_rib, &xang, &yang);
  532.  
  533.           tab_indent();
  534.           fprintf(gOutfile, "translate %#g %#g %#g\n",
  535.               center[X], center[Y], center[Z]);
  536.           tab_indent();
  537.           fprintf(gOutfile, "Rotate %#g 0 1 0\n", yang);  /* was -yang */
  538.           tab_indent();
  539.           fprintf(gOutfile, "Rotate %#g 1 0 0\n", xang);  /* was -xang */
  540.           tab_indent();
  541.           fprintf(gOutfile, "Disk 0 %#g 360\n", oradius);
  542.           tab_dec();
  543.           fprintf(gOutfile, "TransformEnd\n");
  544.         }
  545.         else
  546.           lib_output_polygon_disc(center, normal, iradius, oradius);
  547.         break;
  548.           }
  549.     } else {
  550.     lib_output_polygon_disc(center, normal, iradius, oradius);
  551.     }
  552. }
  553.  
  554.  
  555. /*-----------------------------------------------------------------*/
  556. static void
  557. sq_sphere_val(a1, a2, a3, n, e, u, v, P)
  558.     double a1, a2, a3, n, e, u, v;
  559.     COORD3 P;
  560. {
  561.     double cu, su, cv, sv;
  562.     double icu, isu, icv, isv;
  563.  
  564.     cu = cos(u); su = sin(u);
  565.     cv = cos(v); sv = sin(v);
  566.     icu = SGN(cu); isu = SGN(su);
  567.     icv = SGN(cv); isv = SGN(sv);
  568.     cu = fabs(cu); cv = fabs(cv);
  569.     su = fabs(su); sv = fabs(sv);
  570.     P[X] = a1 * POW(cv, n) * POW(cu, e) * icv * icu;
  571.     P[Y] = a2 * POW(cv, n) * POW(su, e) * icv * isu;
  572.     P[Z] = a3 * POW(sv, n) * isv;
  573. }
  574.  
  575. /*-----------------------------------------------------------------*/
  576. static void
  577. sq_sphere_norm(a1, a2, a3, n, e, u, v, N)
  578.     double a1, a2, a3, n, e, u, v;
  579.     COORD3 N;
  580. {
  581.     double cu, su, cv, sv;
  582.     double icu, isu, icv, isv;
  583.  
  584.     cu = cos(u); su = sin(u);
  585.     cv = cos(v); sv = sin(v);
  586.     icu = SGN(cu); isu = SGN(su);
  587.     icv = SGN(cv); isv = SGN(sv);
  588.  
  589.     /* May be some singularities in the values, lets catch them & put
  590.       a fudged normal into N */
  591.     if (e < 2 || n < 2) {
  592.     if (ABSOLUTE(cu) < 1.0e-3 || ABSOLUTE(su) < 1.0e-3 ||
  593.         ABSOLUTE(cu) < 1.0e-3 || ABSOLUTE(su) < 1.0e-3) {
  594.        SET_COORD3(N, cu*cv, su*cv, sv);
  595.        lib_normalize_vector(N);
  596.        return;
  597.     }
  598.     }
  599.  
  600.     cu = fabs(cu); cv = fabs(cv);
  601.     su = fabs(su); sv = fabs(sv);
  602.  
  603.     N[X] = a1 * POW(cv, 2-n) * POW(cu, 2-e) * icv * icu;
  604.     N[Y] = a2 * POW(cv, 2-n) * POW(su, 2-e) * icv * isu;
  605.     N[Z] = a3 * POW(sv, 2-n) * isv;
  606.     lib_normalize_vector(N);
  607. }
  608.  
  609. /*-----------------------------------------------------------------*/
  610. void
  611. lib_output_sq_sphere(center_pt, a1, a2, a3, n, e)
  612.     COORD3 center_pt;
  613.     double a1, a2, a3, n, e;
  614. {
  615.     object_ptr new_object;
  616.     int i, j, u_res, v_res;
  617.     double u, delta_u, v, delta_v;
  618.     COORD3 verts[4], norms[4];
  619.  
  620.     if (gRT_out_format == OUTPUT_DELAYED) {
  621.        /* Save all the pertinent information */
  622.        new_object = (object_ptr)malloc(sizeof(struct object_struct));
  623.        if (new_object == NULL)
  624.        /* Quietly fail */
  625.        return;
  626.        new_object->object_type  = SUPERQ_OBJ;
  627.        new_object->curve_format = OUTPUT_PATCHES;
  628.        new_object->surf_index   = gTexture_count;
  629.        COPY_COORD4(new_object->object_data.superq.center_pt, center_pt);
  630.        new_object->object_data.superq.a1 = a1;
  631.        new_object->object_data.superq.a2 = a2;
  632.        new_object->object_data.superq.a3 = a3;
  633.        new_object->object_data.superq.n  = n;
  634.        new_object->object_data.superq.e  = e;
  635.        new_object->next_object = gLib_objects;
  636.        gLib_objects = new_object;
  637.        return;
  638.     }
  639.  
  640.     u_res = 4 * gU_resolution;
  641.     v_res = 4 * gV_resolution;
  642.     delta_u = 2.0 * PI / (double)u_res;
  643.     delta_v = PI / (double)v_res;
  644.  
  645.     for (i=0,u=0.0;i<u_res;i++,u+=delta_u) {
  646.     PLATFORM_MULTITASK();
  647.     for (j=0,v=-PI/2.0;j<v_res;j++,v+=delta_v) {
  648.         if (j == 0) {
  649.         sq_sphere_val(a1, a2, a3, n, e, u, v, verts[0]);
  650.         sq_sphere_norm(a1, a2, a3, n, e, u, v, norms[0]);
  651.         sq_sphere_val(a1, a2, a3, n, e, u, v+delta_v, verts[1]);
  652.         sq_sphere_norm(a1, a2, a3, n, e, u, v+delta_v, norms[1]);
  653.         sq_sphere_val(a1, a2, a3, n, e, u+delta_u, v+delta_v, verts[2]);
  654.         sq_sphere_norm(a1, a2, a3, n, e, u+delta_u, v+delta_v,norms[2]);
  655.         ADD3_COORD3(verts[0], verts[0], center_pt);
  656.         ADD3_COORD3(verts[1], verts[1], center_pt);
  657.         ADD3_COORD3(verts[2], verts[2], center_pt);
  658.         lib_output_polypatch(3, verts, norms);
  659.         } else if (j == v_res-1) {
  660.         sq_sphere_val(a1, a2, a3, n, e, u, v, verts[0]);
  661.         sq_sphere_norm(a1, a2, a3, n, e, u, v, norms[0]);
  662.         sq_sphere_val(a1, a2, a3, n, e, u, v+delta_v, verts[1]);
  663.         sq_sphere_norm(a1, a2, a3, n, e, u, v+delta_v, norms[1]);
  664.         sq_sphere_val(a1, a2, a3, n, e, u+delta_u, v, verts[2]);
  665.         sq_sphere_norm(a1, a2, a3, n, e, u+delta_u, v, norms[2]);
  666.         ADD3_COORD3(verts[0], verts[0], center_pt);
  667.         ADD3_COORD3(verts[1], verts[1], center_pt);
  668.         ADD3_COORD3(verts[2], verts[2], center_pt);
  669.         lib_output_polypatch(3, verts, norms);
  670.         } else {
  671.         sq_sphere_val(a1, a2, a3, n, e, u, v, verts[0]);
  672.         sq_sphere_norm(a1, a2, a3, n, e, u, v, norms[0]);
  673.         sq_sphere_val(a1, a2, a3, n, e, u, v+delta_v, verts[1]);
  674.         sq_sphere_norm(a1, a2, a3, n, e, u, v+delta_v, norms[1]);
  675.         sq_sphere_val(a1, a2, a3, n, e, u+delta_u, v+delta_v, verts[2]);
  676.         sq_sphere_norm(a1, a2, a3, n, e, u+delta_u, v+delta_v,norms[2]);
  677.         ADD3_COORD3(verts[0], verts[0], center_pt);
  678.         ADD3_COORD3(verts[1], verts[1], center_pt);
  679.         ADD3_COORD3(verts[2], verts[2], center_pt);
  680.         lib_output_polypatch(3, verts, norms);
  681.         COPY_COORD3(verts[1], verts[2]);
  682.         COPY_COORD3(norms[1], norms[2]);
  683.         sq_sphere_val(a1, a2, a3, n, e, u+delta_u, v, verts[2]);
  684.         sq_sphere_norm(a1, a2, a3, n, e, u+delta_u, v, norms[2]);
  685.         ADD3_COORD3(verts[2], verts[2], center_pt);
  686.         lib_output_polypatch(3, verts, norms);
  687.         }
  688.     }
  689.     }
  690. }
  691.  
  692.  
  693. /*-----------------------------------------------------------------*/
  694. /*
  695.  * Output sphere.  A sphere is defined by a radius and center position.
  696.  *
  697.  * If format=OUTPUT_CURVES, output the sphere in format:
  698.  *     "s" center.x center.y center.z radius
  699.  *
  700.  * If the format=OUTPUT_POLYGONS, the sphere is polygonalized and output.
  701.  * The sphere is polygonalized by splitting it into 6 faces (of a cube
  702.  * projected onto the sphere) and dividing these faces by equally spaced
  703.  * great circles.  OUTPUT_RESOLUTION affects the number of great circles.
  704.  * (6*2*gU_resolution*gV_resolution) polygons are output as triangles
  705.  * using lib_output_polypatch.
  706.  */
  707. void
  708. lib_output_sphere(center_pt, curve_format)
  709.     COORD4 center_pt;
  710.     int curve_format;
  711. {
  712.     object_ptr new_object;
  713.  
  714.     if (gRT_out_format == OUTPUT_DELAYED) {
  715.     /* Save all the pertinent information */
  716.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  717.     if (new_object == NULL)
  718.         /* Quietly fail */
  719.         return;
  720.     new_object->object_type  = SPHERE_OBJ;
  721.     new_object->curve_format = curve_format;
  722.     new_object->surf_index   = gTexture_count;
  723.     COPY_COORD4(new_object->object_data.sphere.center_pt, center_pt);
  724.     new_object->next_object = gLib_objects;
  725.     gLib_objects = new_object;
  726.     }
  727.     else if (curve_format == OUTPUT_CURVES) {
  728.     switch (gRT_out_format) {
  729.         case OUTPUT_VIDEO:
  730.         case OUTPUT_PLG:
  731.         lib_output_polygon_sphere(center_pt);
  732.         break;
  733.  
  734.         case OUTPUT_NFF:
  735.         fprintf(gOutfile, "s %g %g %g %g\n",
  736.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  737.         break;
  738.  
  739.         case OUTPUT_POVRAY_10:
  740.         tab_indent();
  741.         fprintf(gOutfile, "object { sphere { <%g %g %g> %g }",
  742.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  743.         if (gTexture_name != NULL)
  744.             fprintf(gOutfile, " texture { %s }", gTexture_name);
  745.         fprintf(gOutfile, " }\n");
  746.         fprintf(gOutfile, "\n");
  747.         break;
  748.  
  749.         case OUTPUT_POVRAY_20:
  750.         tab_indent();
  751.         fprintf(gOutfile, "sphere { <%g, %g, %g>, %g",
  752.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  753.         if (gTexture_name != NULL)
  754.             fprintf(gOutfile, " texture { %s }", gTexture_name);
  755.         fprintf(gOutfile, " }\n");
  756.         fprintf(gOutfile, "\n");
  757.         break;
  758.  
  759.         case OUTPUT_POLYRAY:
  760.         tab_indent();
  761.         fprintf(gOutfile, "object { sphere <%g, %g, %g>, %g",
  762.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  763.         if (gTexture_name != NULL)
  764.             fprintf(gOutfile, " %s", gTexture_name);
  765.         fprintf(gOutfile, " }\n");
  766.         fprintf(gOutfile, "\n");
  767.         break;
  768.  
  769.         case OUTPUT_VIVID:
  770.         tab_indent();
  771.         fprintf(gOutfile, "sphere { center %g %g %g radius %g }\n",
  772.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  773.         fprintf(gOutfile, "\n");
  774.         break;
  775.  
  776.         case OUTPUT_QRT:
  777.         tab_indent();
  778.         fprintf(gOutfile, "sphere ( loc = (%g, %g, %g), radius = %g )\n",
  779.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  780.         break;
  781.  
  782.         case OUTPUT_RAYSHADE:
  783.         fprintf(gOutfile, "sphere ");
  784.         if (gTexture_name != NULL)
  785.             fprintf(gOutfile, "%s ", gTexture_name);
  786.         fprintf(gOutfile, " %g %g %g %g\n",
  787.             center_pt[W], center_pt[X], center_pt[Y], center_pt[Z]);
  788.         break;
  789.  
  790.         case OUTPUT_RTRACE:
  791.         fprintf(gOutfile, "1 %d %g %g %g %g %g\n",
  792.             gTexture_count, gTexture_ior,
  793.             center_pt[X], center_pt[Y], center_pt[Z], center_pt[W]);
  794.         break;
  795.  
  796.         case OUTPUT_ART:
  797.         tab_indent();
  798.         fprintf(gOutfile, "sphere {\n");
  799.         tab_inc();
  800.  
  801.         tab_indent();
  802.         fprintf(gOutfile, "radius %g\n", center_pt[W]);
  803.         tab_indent();
  804.         fprintf(gOutfile, "center(%g, %g, %g)\n",
  805.             center_pt[X], center_pt[Y], center_pt[Z]);
  806.  
  807.         tab_dec();
  808.         tab_indent();
  809.         fprintf(gOutfile, "}\n");
  810.         fprintf(gOutfile, "\n");
  811.         break;
  812.  
  813.         case OUTPUT_RAWTRI:
  814.         case OUTPUT_DXF:
  815.         lib_output_polygon_sphere(center_pt);
  816.         break;
  817.           case OUTPUT_RIB:
  818.         tab_indent();
  819.         fprintf(gOutfile, "TransformBegin\n");
  820.         tab_inc();
  821.         tab_indent();
  822.         fprintf(gOutfile, "Translate %#g %#g %#g\n",
  823.             center_pt[X], center_pt[Y], center_pt[Z]);
  824.         tab_indent();
  825.         fprintf(gOutfile, "Sphere %#g %#g %#g 360\n",
  826.             center_pt[W], -center_pt[W], center_pt[W]);
  827.         tab_dec();
  828.         tab_indent();
  829.         fprintf(gOutfile, "TransformEnd\n");
  830.         break;
  831.     }
  832.     } else {
  833.     lib_output_polygon_sphere(center_pt);
  834.     }
  835. }
  836.  
  837.  
  838.  
  839. /*-----------------------------------------------------------------*/
  840. /* Output box.  A box is defined by a diagonally opposite corners. */
  841. void
  842. lib_output_box(p1, p2)
  843.     COORD3 p1, p2;
  844. {
  845.     object_ptr new_object;
  846.  
  847.     if (gRT_out_format == OUTPUT_DELAYED) {
  848.     /* Save all the pertinent information */
  849.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  850.     if (new_object == NULL)
  851.         /* Quietly fail */
  852.         return;
  853.     new_object->object_type  = BOX_OBJ;
  854.     new_object->curve_format = OUTPUT_PATCHES;
  855.     new_object->surf_index   = gTexture_count;
  856.     COPY_COORD3(new_object->object_data.box.point1, p1);
  857.     COPY_COORD3(new_object->object_data.box.point2, p2);
  858.     new_object->next_object = gLib_objects;
  859.     gLib_objects = new_object;
  860.     } else {
  861.     switch (gRT_out_format) {
  862.         case OUTPUT_VIDEO:
  863.         case OUTPUT_NFF:
  864.         case OUTPUT_VIVID:
  865.         case OUTPUT_PLG:
  866.         case OUTPUT_RAWTRI:
  867.         case OUTPUT_RIB:
  868.         case OUTPUT_DXF:
  869.         lib_output_polygon_box(p1, p2);
  870.         break;
  871.  
  872.         case OUTPUT_POVRAY_10:
  873.         tab_indent();
  874.         fprintf(gOutfile, "object { box { <%g %g %g> <%g %g %g> }",
  875.             p1[X], p1[Y], p1[Z], p2[X], p2[Y], p2[Z]);
  876.         if (gTexture_name != NULL)
  877.             fprintf(gOutfile, " texture { %s }", gTexture_name);
  878.         fprintf(gOutfile, " }\n");
  879.         fprintf(gOutfile, "\n");
  880.         break;
  881.  
  882.         case OUTPUT_POVRAY_20:
  883.         tab_indent();
  884.         fprintf(gOutfile, "box { <%g, %g, %g>, <%g, %g, %g>  ",
  885.             p1[X], p1[Y], p1[Z], p2[X], p2[Y], p2[Z]);
  886.         if (gTexture_name != NULL)
  887.             fprintf(gOutfile, " texture { %s }", gTexture_name);
  888.         fprintf(gOutfile, " }\n");
  889.         fprintf(gOutfile, "\n");
  890.         break;
  891.  
  892.         case OUTPUT_POLYRAY:
  893.         fprintf(gOutfile, "object { box <%g, %g, %g>, <%g, %g, %g>",
  894.             p1[X], p1[Y], p1[Z], p2[X], p2[Y], p2[Z]);
  895.         if (gTexture_name != NULL)
  896.             fprintf(gOutfile, " %s", gTexture_name);
  897.         fprintf(gOutfile, " }\n");
  898.         fprintf(gOutfile, "\n");
  899.         break;
  900.  
  901.         case OUTPUT_QRT:
  902.         fprintf(gOutfile, "BEGIN_BBOX\n");
  903.         lib_output_polygon_box(p1, p2);
  904.         fprintf(gOutfile, "END_BBOX\n");
  905.         break;
  906.  
  907.         case OUTPUT_RAYSHADE:
  908.         fprintf(gOutfile, "box ");
  909.         if (gTexture_name != NULL)
  910.             fprintf(gOutfile, "%s ", gTexture_name);
  911.         fprintf(gOutfile, " %g %g %g %g %g %g\n",
  912.             p1[X], p1[Y], p1[Z], p2[X], p2[Y], p2[Z]);
  913.         break;
  914.  
  915.         case OUTPUT_ART:
  916.         tab_indent();
  917.         fprintf(gOutfile, "box {");
  918.         fprintf(gOutfile, " vertex(%g, %g, %g)\n",
  919.             p1[X], p1[Y], p1[Z]);
  920.         fprintf(gOutfile, " vertex(%g, %g, %g) }\n",
  921.             p2[X], p2[Y], p2[Z]);
  922.         fprintf(gOutfile, "\n");
  923.         break;
  924.  
  925.         case OUTPUT_RTRACE:
  926.         fprintf(gOutfile, "2 %d %g %g %g %g %g %g %g\n",
  927.             gTexture_count, gTexture_ior,
  928.             (p1[X] + p2[X]) / 2.0,
  929.             (p1[Y] + p2[Y]) / 2.0,
  930.             (p1[Z] + p2[Z]) / 2.0,
  931.             p2[X] - p1[X], p2[Y] - p1[Y], p2[Z] - p1[Z]);
  932.         break;
  933.     }
  934.     }
  935. }
  936.