home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 564a.lha / igensurf_v1.0 / src.LZH / src / igensurf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-28  |  28.1 KB  |  1,027 lines

  1. /* :ts=8 */    /* Yes some of us still use vi ! */
  2. /************************************************************************/
  3. /*                                                        */
  4. /* Program to generate a TTDDD description of a functional surface.     */
  5. /*                                        */
  6. /* Usage:                                 */
  7. /*                                        */
  8. /*  igensurf [-n name] [-s step_s] [-t step_t]                */
  9. /*         [-C] [-R] [-T] [-S scale_factor] [-p] [-v]            */
  10. /*         [-e expression] [-o output_file] input_file ...        */
  11. /*                                    */
  12. /************************************************************************/
  13. /*                                        */
  14. /* This program is based on the 'gensurf' program found in the Radiance    */
  15. /* Synthetic Imaging System. Radiance (and gensurf) is written by    */
  16. /* Greg Ward.                                */
  17. /*                                     */
  18. /* Igensurf produces a TTDDD object description of a functional surface    */
  19. /* defined by the parametric equations x(s,t), y(s,t) and z(s,t).    */
  20. /* The object is scaled by the factor given with the -S option.        */
  21. /*                                     */
  22. /* The surface normal is defined ny the right and rule as applied to    */
  23. /* (s,t). S will vary from 0 to 1 in steps of 1/step_s, and t will vary */
  24. /* from 0 to 1 in steps of 1/step_t. The surface will be composed of     */
  25. /* 2 * step_s * step_t or fewer triangles.                */
  26. /*                                     */
  27. /* -n defines name of the generated object.                */
  28. /* -C enables generation of face color info.                */
  29. /* -R enables generation of face reflectance info.            */
  30. /* -T enables generation of face transmittance info.            */
  31. /* -S defines a scale factor.                        */
  32. /* -p enables phong smothing of the surface.                */
  33. /* -v enables writing of some messages to stderr.            */
  34. /* -e defines extra expressions (can be repeated).            */
  35. /* -o defines name of the TTDDD output file (default is stdout).    */
  36. /*                                    */
  37. /* See the 'igensurf.doc' file for further information.            */
  38. /*                                    */
  39. /************************************************************************/
  40. /*                                    */
  41. /* EXAMPLE:                                */
  42. /*                                    */
  43. /*   To generate a sphere:                        */
  44. /*                                    */
  45. /*   igensurf -n ball -e "x(s,t)=sin(PI*s)*cos(2*PI*t)"         */
  46. /*          -e "y(x,t)=cos(PI*s)" -e "z(x,t)=sin(PI*s)*sin(2*PI*t)"     */
  47. /*           -s 7 -t 10 -S 100 -o ball.ttddd                */
  48. /*                                     */
  49. /*   writetddd ball.ttddd ball.obj                    */
  50. /*                                     */
  51. /* You can of course use a pipe instead of using a temporary file.    */
  52. /*                                     */
  53. /************************************************************************/
  54. /*                                    */
  55. /* BUGS:                                */
  56. /*                                    */
  57. /* Has limits on object sizes. These may be changed by recompiling after*/
  58. /* changing some defines below.                                     */
  59. /* It might also be necessary to change the sizes if you are using a     */
  60. /* 512 K machine.                            */
  61. /*                                     */
  62. /* All points, edges and faces are saved in arrays. The program does a    */
  63. /* linear search for points before adding new points. This method can    */
  64. /* be very time consuming for big objects.                */
  65. /*                                    */
  66. /* igensurf doesn't free allocated space itself. Hopefully the OS, or     */
  67. /* the compiler will do it. It only uses standard malloc calls.     */
  68. /*                                    */
  69. /************************************************************************/
  70. /*                                                                      */
  71. /* Author:  Helge E. Rasmussen  (her@compel.dk)                         */
  72. /*                                                                      */
  73. /* Original Radiance code by Greg Ward.                    */
  74. /*                                                                      */
  75. /* You may use the program and the source code in any way you want as    */
  76. /* long as you do not resell the software as your own, or use it in a    */
  77. /* commercial product.                            */
  78. /*                                                                      */
  79. /* Please let me know if you find any bugs, or have ideas for enhance-    */
  80. /* ments.                                 */
  81. /*                                                                      */
  82. /************************************************************************/
  83.  
  84. #define Version    "v. 1.0"    /* Current version of program.    */
  85.  
  86.  
  87.     /* Increase these for very big objects          */
  88.     /* Decrease them if you are using a 512 K machine    */
  89.     
  90. #define Max_Nbr_Points    10000
  91. #define Max_Nbr_Edges    10000
  92. #define Max_Nbr_Faces    10000
  93.  
  94.  
  95. #include <math.h>
  96. #include <stdio.h>
  97. #include <string.h>
  98. #include <ctype.h>
  99. #include <errno.h>
  100. #ifdef AMIGA
  101. #include <stdlib.h>
  102. #else
  103. #include <unistd.h>
  104. #endif
  105.  
  106. #include "calc.h"
  107.  
  108. #ifndef PI
  109. #define PI     M_PI
  110. #endif
  111.  
  112. #ifndef TRUE
  113. #define TRUE      1
  114. #define FALSE     0
  115. #endif 
  116.  
  117. #define FTINY        (double) 1e-6
  118. #define Buffer_Length    256
  119. #define ABS(x)        ((x)>=0 ? (x) : -(x))
  120.  
  121. typedef int            Boolean_T;
  122.  
  123. typedef struct {
  124.     unsigned char R;
  125.     unsigned char G;
  126.     unsigned char B;
  127. } Color_T;
  128.  
  129. typedef struct {
  130.     double    X;
  131.     double    Y;
  132.     double    Z;
  133. } Vector_T;
  134.  
  135. typedef struct {
  136.     int        P1;
  137.     int        P2;
  138. } Edge_T;
  139.  
  140. typedef struct {
  141.     int        E1;
  142.     int        E2;
  143.     int        E3;
  144.     Color_T        Color;
  145.     Color_T        Refl;
  146.     Color_T        Trans;
  147. } Face_T;
  148.  
  149. #define  X_FUNC        "x"        /* x function name         */
  150. #define  Y_FUNC        "y"        /* y function name         */
  151. #define  Z_FUNC        "z"        /* z function name         */
  152. #define  CR_FUNC    "cr"        /* color R function name     */
  153. #define  CG_FUNC    "cg"        /* color G function name     */
  154. #define  CB_FUNC    "cb"        /* color B function name     */
  155. #define  RR_FUNC    "rr"        /* refl. R function name     */
  156. #define  RG_FUNC    "rg"        /* refl. G function name     */
  157. #define  RB_FUNC    "rb"        /* refl. B function name     */
  158. #define  TR_FUNC    "tr"        /* trans R function name     */
  159. #define  TG_FUNC    "rg"        /* trans G function name     */
  160. #define  TB_FUNC    "tb"        /* trans B function name     */
  161.  
  162. char       Object_Name[Buffer_Length+1];/* Name of object.        */
  163.  
  164. Boolean_T  Verbose      = FALSE;    /* Be verbose              */
  165. Boolean_T  Phong        = FALSE;    /* Phong smoothing?        */
  166. Boolean_T  Compute_Color = FALSE;    /* Compute color        */
  167. Boolean_T  Compute_Refl  = FALSE;    /* Compute reflectance        */
  168. Boolean_T  Compute_Trans = FALSE;    /* Compute transmittance    */
  169. int       Step_S     = 10;        /* Number of steps (s).        */
  170. int       Step_T     = 10;        /* Number of steps (t).        */
  171. double       Scale_Factor  = 1.0;        /* Scale factor            */
  172. double       Precision     = 1e-7;    /* Precision in coordinates     */
  173. Vector_T   *Row0     = NULL;
  174. Vector_T   *Row1     = NULL;
  175. Vector_T   *Row2     = NULL;
  176. FILE       *O_Stream     = NULL;
  177. Boolean_T  Generate_Done = FALSE;
  178.  
  179. Vector_T    Points[Max_Nbr_Points];        /* Table of points    */
  180. int        Nbr_Points    = 0;
  181.  
  182. Edge_T        Edges[Max_Nbr_Edges];        /* Table of edges    */
  183. int        Nbr_Edges    = 0;
  184.  
  185. Face_T        Faces[Max_Nbr_Faces];        /* Table of faces    */
  186. int        Nbr_Faces     = 0;
  187.  
  188.  
  189. void Error(Txt)
  190. char    *Txt;
  191. /************************************************************************/
  192. /*                                    */
  193. /* Write error messages and stop the program.                           */
  194. /*                                    */
  195. /************************************************************************/
  196. {
  197.  
  198.     fprintf(stderr, "Error: %s\n", Txt);
  199.     exit(9);
  200.  
  201. } /* Error */
  202.  
  203.  
  204. void Usage()
  205. /************************************************************************/
  206. /*                                    */
  207. /* Write a usage message to stderr, and stop the program.        */
  208. /*                                    */
  209. /************************************************************************/
  210. {
  211.  
  212.     fprintf(stderr, "Usage: igensurf [-n name] [-s step_s] [-t step_t]\n");
  213.     fprintf(stderr, "  [-C] [-R] [-T] [-S scale_factor] [-p] [-v]\n");
  214.     fprintf(stderr, "  [-e expression] [-o output_file] input_file ...\n");
  215.     exit(1);
  216.  
  217. } /* Usage */
  218.  
  219.  
  220. int Get_Point(Point)
  221. Vector_T    *Point;
  222. /************************************************************************/
  223. /*                                    */
  224. /* Get id for the point 'Point'.                    */
  225. /* If no such point exist, then create it and return the newly created  */
  226. /* id.                                                                  */
  227. /*                                    */
  228. /************************************************************************/
  229. {
  230.     int    i;
  231.  
  232.     for (i = Nbr_Points-1; i >= 0; i--) {
  233.  
  234.     if (ABS(Point->X - Points[i].X) < Precision &&
  235.         ABS(Point->Y - Points[i].Y) < Precision &&
  236.         ABS(Point->Z - Points[i].Z) < Precision) return(i);
  237.  
  238.     } /* for */
  239.  
  240.     if (Nbr_Points >= Max_Nbr_Points) Error("Too many points");
  241.  
  242.     Points[Nbr_Points].X = Point->X;
  243.     Points[Nbr_Points].Y = Point->Y;
  244.     Points[Nbr_Points].Z = Point->Z;
  245.  
  246.     return(Nbr_Points++);
  247.  
  248. } /* Get_Point */
  249.  
  250. int Get_Edge(P1, P2)
  251. int    P1;
  252. int    P2;
  253. /************************************************************************/
  254. /*                                    */
  255. /* Get id for the edge that connects the points P1 and P2.              */
  256. /* If no such edge exists, then create it and return the newly created  */
  257. /* id.                                                                  */
  258. /*                                    */
  259. /************************************************************************/
  260. {
  261.     int    i;
  262.  
  263.     for (i = Nbr_Edges-1; i >= 0; i--) {
  264.  
  265.     if ( (Edges[i].P1 == P1 && Edges[i].P2 == P2) ||
  266.          (Edges[i].P1 == P2 && Edges[i].P2 == P1) ) return(i);
  267.  
  268.     } /* for */
  269.  
  270.     if (Nbr_Edges >= Max_Nbr_Edges) Error("Too many edges");
  271.  
  272.     Edges[Nbr_Edges].P1 = P1;
  273.     Edges[Nbr_Edges].P2 = P2;
  274.  
  275.     return(Nbr_Edges++);
  276.  
  277. } /* Get_Edge */
  278.  
  279. void Add_Face(P1, P2, P3, Color, Refl, Trans)
  280. int    P1;
  281. int    P2;
  282. int    P3;
  283. Color_T    *Color;
  284. Color_T    *Refl;
  285. Color_T    *Trans;
  286. /************************************************************************/
  287. /*                                    */
  288. /* Add a new face connecting P1, P2 and P3 to the face table.           */
  289. /* The corresponding edges will be created if they don't exist.         */
  290. /*                                    */
  291. /************************************************************************/
  292. {
  293.     int    i;
  294.     int E1, E2, E3;
  295.  
  296.     E1 = Get_Edge(P1, P2);
  297.     E2 = Get_Edge(P2, P3);
  298.     E3 = Get_Edge(P3, P1);
  299.  
  300.     for (i = Nbr_Faces-1; i >= 0; i--) {
  301.  
  302.     if (Faces[i].E1 == E1 && Faces[i].E2 == E2 &&
  303.                         Faces[i].E3 == E3) return;
  304.  
  305.     } /* for */
  306.  
  307.  
  308.     if (Nbr_Faces >= Max_Nbr_Faces) Error("Too many Faces");
  309.  
  310.     Faces[Nbr_Faces].E1      = Get_Edge(P1, P2);
  311.     Faces[Nbr_Faces].E2      = Get_Edge(P2, P3);
  312.     Faces[Nbr_Faces].E3      = Get_Edge(P3, P1);
  313.  
  314.     Faces[Nbr_Faces].Color.R = Color->R;
  315.     Faces[Nbr_Faces].Color.G = Color->G;
  316.     Faces[Nbr_Faces].Color.B = Color->B;
  317.  
  318.     Faces[Nbr_Faces].Refl.R  = Refl->R;
  319.     Faces[Nbr_Faces].Refl.G  = Refl->G;
  320.     Faces[Nbr_Faces].Refl.B  = Refl->B;
  321.  
  322.     Faces[Nbr_Faces].Trans.R = Trans->R;
  323.     Faces[Nbr_Faces].Trans.G = Trans->G;
  324.     Faces[Nbr_Faces].Trans.B = Trans->B;
  325.  
  326.     Nbr_Faces++;
  327.  
  328. } /* Add_Face */
  329.  
  330. void Write_TTDDD_Object()
  331. /************************************************************************/
  332. /*                                    */
  333. /* Write the object saved in the global variables to O_Stream in TTDDD    */
  334. /* format.                                */
  335. /* Set the name of the object to 'Object_Name'.                         */
  336. /* If 'Phong' is TRUE, the object should be phong smoothed.        */
  337. /*                                    */
  338. /************************************************************************/
  339. {
  340.     int        i;
  341.  
  342.     if (Nbr_Points == 0) return;
  343.  
  344.     if (Verbose) 
  345.     fprintf(stderr, 
  346.       "Generating TTDDD description for %s...\n", Object_Name); 
  347.     
  348.     fprintf(O_Stream, "OBJ Begin   %% Begin Object chunk\n");
  349.     fprintf(O_Stream, "\n");
  350.  
  351.     fprintf(O_Stream, "DESC Begin  %% Begin DESC sub-chunk\n");
  352.     fprintf(O_Stream, "\n");
  353.  
  354.     fprintf(O_Stream, "\tNAME \"%s\"\n", Object_Name);
  355.     fprintf(O_Stream, "\n");
  356.     fprintf(O_Stream, "\tSHAP Shape 2   %% Axis object\n");
  357.     fprintf(O_Stream, "\tSHAP Lamp  0   %% Not a lamp\n");
  358.     fprintf(O_Stream, "\n");
  359.     fprintf(O_Stream, "\tPOSI X=0.0 Y=0.0 Z=0.0 %% Position.\n");
  360.     fprintf(O_Stream, "\n");
  361.  
  362.     fprintf(O_Stream, "\tAXIS XAxis X=1 %% Defaults to 1 0 0\n");
  363.     fprintf(O_Stream, "\tAXIS YAxis Y=1 %% Defaults to 0 1 0\n");
  364.     fprintf(O_Stream, "\tAXIS ZAxis Z=1 %% Defaults to 0 0 1\n");
  365.     fprintf(O_Stream, "\n");
  366.  
  367.     fprintf(O_Stream, "\tSIZE X=32 Y=32 Z=32 %% Defaults to 32.0\n");
  368.     fprintf(O_Stream, "\n");
  369.  
  370.         /* POINTS */
  371.  
  372.     if (Verbose) fprintf(stderr, "Points (%d)...\n", Nbr_Points);
  373.     
  374.     fprintf(O_Stream, "\tPNTS PCount %d %% Number of points\n", Nbr_Points);
  375.     fprintf(O_Stream, "\n");
  376.     for (i = 0; i < Nbr_Points; i++) {
  377.         fprintf(O_Stream, "\tPNTS Point[%d] %lf %lf %lf\n", 
  378.                 i, 
  379.                 Scale_Factor * Points[i].X, 
  380.                 Scale_Factor * Points[i].Y, 
  381.                 Scale_Factor * Points[i].Z);
  382.     } /* for */
  383.     fprintf(O_Stream, "\n");
  384.  
  385.  
  386.         /* EDGES */
  387.     if (Verbose) fprintf(stderr, "Edges (%d)...\n", Nbr_Edges);
  388.  
  389.     fprintf(O_Stream, "\tEDGE ECount %d %% Number of edges\n", Nbr_Edges);
  390.     fprintf(O_Stream, "\n");
  391.     for (i = 0; i < Nbr_Edges; i++) {
  392.         fprintf(O_Stream, "\tEDGE Edge[%d] %d %d\n", 
  393.                 i, Edges[i].P1, Edges[i].P2);
  394.     } /* for */
  395.     fprintf(O_Stream, "\n");
  396.  
  397.  
  398.         /* FACES */
  399.     if (Verbose) fprintf(stderr, "Faces (%d)...\n", Nbr_Faces);
  400.  
  401.     fprintf(O_Stream, "\tFACE TCount %d %% Number of faces\n", Nbr_Faces);
  402.     fprintf(O_Stream, "\n");
  403.     for (i = 0; i < Nbr_Faces; i++) {
  404.         fprintf(O_Stream, "\tFACE Connect[%d] %d %d %d\n", 
  405.                 i, Faces[i].E1, Faces[i].E2, Faces[i].E3);
  406.     } /* for */
  407.     fprintf(O_Stream, "\n");
  408.  
  409.  
  410.     if (Compute_Color) {
  411.  
  412.         /* COLORS */
  413.         if (Verbose) fprintf(stderr, "Colors (%d)...\n", Nbr_Faces);
  414.  
  415.         fprintf(O_Stream, "\tCLST Count %d %% Number of colors\n",Nbr_Faces);
  416.         fprintf(O_Stream, "\n");
  417.         for (i = 0; i < Nbr_Faces; i++) {
  418.             fprintf(O_Stream, "\tCLST Color[%d] %d %d %d\n",  i, 
  419.                 Faces[i].Color.R,
  420.                 Faces[i].Color.G,
  421.                 Faces[i].Color.B);
  422.         } /* for */
  423.         fprintf(O_Stream, "\n");
  424.  
  425.     } /* if */
  426.  
  427.     if (Compute_Refl) {
  428.  
  429.         /* COLORS */
  430.         if (Verbose) fprintf(stderr, "Reflectance (%d)...\n", Nbr_Faces);
  431.  
  432.         fprintf(O_Stream, "\tRLST Count %d %% Number of colors\n",Nbr_Faces);
  433.         fprintf(O_Stream, "\n");
  434.         for (i = 0; i < Nbr_Faces; i++) {
  435.             fprintf(O_Stream, "\tRLST Color[%d] %d %d %d\n",  i, 
  436.                 Faces[i].Refl.R,
  437.                 Faces[i].Refl.G,
  438.                 Faces[i].Refl.B);
  439.         } /* for */
  440.         fprintf(O_Stream, "\n");
  441.  
  442.     } /* if */
  443.  
  444.     if (Compute_Trans) {
  445.  
  446.         /* COLORS */
  447.         if (Verbose) fprintf(stderr, "Transmittance (%d)...\n", Nbr_Faces);
  448.  
  449.         fprintf(O_Stream, "\tTLST Count %d %% Number of colors\n",Nbr_Faces);
  450.         fprintf(O_Stream, "\n");
  451.         for (i = 0; i < Nbr_Faces; i++) {
  452.             fprintf(O_Stream, "\tTLST Color[%d] %d %d %d\n",  i, 
  453.                 Faces[i].Trans.R,
  454.                 Faces[i].Trans.G,
  455.                 Faces[i].Trans.B);
  456.         } /* for */
  457.         fprintf(O_Stream, "\n");
  458.  
  459.     } /* if */
  460.  
  461.     fprintf(O_Stream, "\tMTTR Type  4   %%\n");
  462.     fprintf(O_Stream, "\tMTTR Index 1.0 %%\n");
  463.     fprintf(O_Stream, "\n");
  464.  
  465.     fprintf(O_Stream, "\tSPEC Specularity 0\n");
  466.     fprintf(O_Stream, "\tSPEC Hardness    0\n");
  467.     fprintf(O_Stream, "\n");
  468.  
  469.     fprintf(O_Stream, "\tPRP0[0] 0   %% Blending (dither) factor.\n");
  470.     fprintf(O_Stream, "\tPRP0[1] 0   %% Roughness factor.\n");
  471.     fprintf(O_Stream, "\tPRP0[2] 0   %% Shading on/off.\n");
  472.     fprintf(O_Stream, "\tPRP0[3] %d  %% Phong shading flag.\n", !Phong);
  473.     fprintf(O_Stream, "\tPRP0[4] 0   %% Glossy flag. \n");
  474.     fprintf(O_Stream, "\tPRP0[5] 0   %% Quickdraw flag.\n");
  475.     fprintf(O_Stream, "\n");
  476.  
  477.     fprintf(O_Stream, "End DESC  %% End of DESC sub-chunk\n");
  478.     fprintf(O_Stream, "\n");
  479.  
  480.     fprintf(O_Stream, "TOBJ %% End of object hierachy.\n");
  481.     fprintf(O_Stream, "\n");
  482.  
  483.     fprintf(O_Stream, "End OBJ  %% End of object chunk\n");
  484.     fprintf(O_Stream, "\n");
  485.  
  486.     Nbr_Points = 0;
  487.     Nbr_Edges  = 0;
  488.     Nbr_Faces  = 0;
  489.  
  490. } /* Write_TTDDD_Object */
  491.  
  492.  
  493. Boolean_T Face_Is_Ok(Point0, Point1, Point2)
  494. Vector_T    *Point0;
  495. Vector_T    *Point1;
  496. Vector_T    *Point2;
  497. /************************************************************************/
  498. /*                                    */
  499. /* Check if the three points defines a triangle.            */
  500. /* Return TRUE if they do.                        */
  501. /*                                    */
  502. /************************************************************************/
  503. {
  504.     Vector_T    V1;
  505.     Vector_T    V2;
  506.     double     Vx, Vy, Vz;
  507.  
  508.     V1.X = Point1->X - Point0->X;
  509.     V1.Y = Point1->Y - Point0->Y;
  510.     V1.Z = Point1->Z - Point0->Z;
  511.  
  512.     V2.X = Point2->X - Point0->X;
  513.     V2.Y = Point2->Y - Point0->Y;
  514.     V2.Z = Point2->Z - Point0->Z;
  515.  
  516.         /* Cross product:    */
  517.     Vx = V1.Y * V2.Z - V1.Z * V2.Y;
  518.     Vy = V1.Z * V2.X - V1.X * V2.Z;
  519.     Vz = V1.X * V2.Y - V1.Y * V2.X;
  520.  
  521.     if (ABS(Vx) < FTINY && 
  522.         ABS(Vy) < FTINY && 
  523.         ABS(Vz) < FTINY) return(FALSE);
  524.  
  525.     return(TRUE);
  526.  
  527. } /* Face_Is_Ok */
  528.  
  529.  
  530. void Compute_Face_Info(s, t, Point0, Point1, Point2, Color, Refl, Trans)
  531. double s, t;
  532. Vector_T *Point0, *Point1, *Point2;
  533. Color_T      *Color;
  534. Color_T      *Refl;
  535. Color_T      *Trans;
  536. /************************************************************************/
  537. /*                                    */
  538. /* Compute Color, Reflectance and Transmittance for the face defined by    */
  539. /* Point0, Point1 and Point2 (plus s and t).                */
  540. /*                                    */
  541. /************************************************************************/
  542. {
  543.     double     Arguments[5];
  544.  
  545.     if (!Compute_Color && !Compute_Refl && !Compute_Trans) return;
  546.     Arguments[0] = s;
  547.     Arguments[1] = t;
  548.     Arguments[2] = (Point0->X + Point1->X + Point2->X) / 3.0;
  549.     Arguments[3] = (Point0->Y + Point1->Y + Point2->Y) / 3.0;
  550.     Arguments[4] = (Point0->Z + Point1->Z + Point2->Z) / 3.0;
  551.  
  552.     if (Compute_Color) {
  553.     Color->R = 255.0 * Func_Value(CR_FUNC, 5, Arguments);
  554.     Color->G = 255.0 * Func_Value(CG_FUNC, 5, Arguments);
  555.     Color->B = 255.0 * Func_Value(CB_FUNC, 5, Arguments);
  556.     }
  557.  
  558.     if (Compute_Refl) {
  559.     Refl->R = 255.0 * Func_Value(RR_FUNC, 5, Arguments);
  560.     Refl->G = 255.0 * Func_Value(RG_FUNC, 5, Arguments);
  561.     Refl->B = 255.0 * Func_Value(RB_FUNC, 5, Arguments);
  562.     }
  563.  
  564.     if (Compute_Trans) {
  565.     Trans->R = 255.0 * Func_Value(TR_FUNC, 5, Arguments);
  566.     Trans->G = 255.0 * Func_Value(TG_FUNC, 5, Arguments);
  567.     Trans->B = 255.0 * Func_Value(TB_FUNC, 5, Arguments);
  568.     }
  569.  
  570.  
  571. } /* Compute_Face_Info */
  572.  
  573. void Generate_Face(s, t, Point0, Point1, Point2, Point3)
  574. double s, t;
  575. Vector_T *Point0, *Point1, *Point2, *Point3;
  576. /************************************************************************/
  577. /*                                    */
  578. /* Add the square given by the four points to the face/edge/point lists.*/
  579. /*                                    */
  580. /************************************************************************/
  581. {
  582.     int     Face1_Ok, Face2_Ok;
  583.     int        Point0_Id, Point1_Id, Point2_Id, Point3_Id;
  584.     Color_T    Color, Refl, Trans;
  585.  
  586.     Face1_Ok = Face_Is_Ok(Point0, Point1, Point2);
  587.     Face2_Ok = Face_Is_Ok(Point1, Point2, Point3);
  588.  
  589.     if (Face1_Ok || Face2_Ok) {
  590.  
  591.            if (Face1_Ok) Point0_Id = Get_Point(Point0);
  592.  
  593.         Point1_Id = Get_Point(Point1);
  594.         Point2_Id = Get_Point(Point2);
  595.  
  596.         if (Face2_Ok) Point3_Id = Get_Point(Point3);
  597.  
  598.     if (Face1_Ok)  {
  599.         Compute_Face_Info(s, t, Point0, Point1, Point2, 
  600.                         &Color, &Refl, &Trans);
  601.         Add_Face(Point0_Id, Point1_Id, Point2_Id, 
  602.                         &Color, &Refl, &Trans);
  603.     }
  604.  
  605.     if (Face2_Ok)  {
  606.         Compute_Face_Info(s, t, Point2, Point1, Point3, 
  607.                         &Color, &Refl, &Trans);
  608.         Add_Face(Point2_Id, Point1_Id, Point3_Id,
  609.                         &Color, &Refl, &Trans);
  610.     }
  611.  
  612.     } /* if */
  613.  
  614. } /* Generate_Face */
  615.  
  616. Compute_Row(s, Row, Step_Size)
  617. double        s;
  618. register Vector_T *Row;
  619. int            Step_Size;
  620. /************************************************************************/
  621. /*                                    */
  622. /* Compute row of values for a given 's'.                */
  623. /*                                    */
  624. /************************************************************************/
  625. {
  626.     double        Arguments[2];
  627.     int        end;
  628.     register int  i;
  629.     
  630.     
  631.     if (s < -FTINY || s > 1.0+FTINY) return;
  632.  
  633.     i   = 0;
  634.     end = Step_Size;
  635.  
  636.     Arguments[0] = s;
  637.  
  638.     while (i <= end) {
  639.  
  640.     Arguments[1] = (double) i / Step_Size;
  641.  
  642.     Row[i].X = Func_Value(X_FUNC, 2, Arguments);
  643.     Row[i].Y = Func_Value(Y_FUNC, 2, Arguments);
  644.     Row[i].Z = Func_Value(Z_FUNC, 2, Arguments);
  645.  
  646.     i++;
  647.  
  648.     } /* while */
  649.  
  650.  
  651. } /* Compute_Row */
  652.  
  653. int    Generate_Object()
  654. /************************************************************************/
  655. /*                                    */
  656. /* Generate the points, edges and faces of the current object.        */
  657. /*                                    */
  658. /************************************************************************/
  659. {
  660.     int        i, j;
  661.     int        New_Step_S;
  662.     int        New_Step_T;
  663.     Vector_T    *Tmp_Row;
  664.  
  665.  
  666.     /* Get Step_S and Step_T from user variables.        */
  667.  
  668.     New_Step_S = Var_Value("step_s");
  669.     New_Step_T = Var_Value("step_t");
  670.  
  671.     if (New_Step_S <= 0  || New_Step_T <= 0 ||
  672.         New_Step_S > 999 || New_Step_T > 999) {
  673.  
  674.         fprintf(stderr, "Illegal values for step_s (%d) or step_t (%d)\n",
  675.                         New_Step_S, New_Step_T);
  676.     exit(1);
  677.  
  678.     } /* if */
  679.  
  680.     /* Allocate space for three rows if they have changed size.    */
  681.  
  682.     if (Row0 == NULL || Step_T != New_Step_T) {
  683.  
  684.     if (Row0 != NULL) free(Row0);
  685.         Row0 = (Vector_T *) malloc( (New_Step_T+3) * sizeof(Vector_T) );
  686.         if (Row0 == NULL) Error("Error in malloc");
  687.  
  688.     if (Row1 != NULL) free(Row1);
  689.         Row1 = (Vector_T *) malloc( (New_Step_T+3) * sizeof(Vector_T) );
  690.         if (Row1 == NULL) Error("Error in malloc");
  691.  
  692.     if (Row2 != NULL) free(Row2);
  693.         Row2 = (Vector_T *) malloc( (New_Step_T+3) * sizeof(Vector_T) );
  694.         if (Row2 == NULL) Error("Error in malloc");
  695.  
  696.  
  697.     } /* if */
  698.  
  699.     Step_S = New_Step_S;
  700.     Step_T = New_Step_T;
  701.  
  702.  
  703.  
  704.     if (Verbose) fprintf(stderr, "Computing surfaces (%d):\n", Step_S - 1);
  705.  
  706.     /* Initialize the first rows                */
  707.     /* It is not neccessary to initialize Row0, as it is    */
  708.     /* computed as the first step in the main loop.        */
  709.  
  710.     Compute_Row(0.0, Row1, Step_T);
  711.     Compute_Row(1.0/Step_S, Row2, Step_T);
  712.     
  713.         
  714.     for (i = 0; i < Step_S; i++) {
  715.  
  716.         if (Verbose) {
  717.         if ( i != 0 && i % 10 == 0) fprintf(stderr, "%d", i);
  718.         else                        fprintf(stderr, ".");
  719.     }
  720.                         /* compute next row */
  721.     Tmp_Row = Row0;
  722.     Row0    = Row1;
  723.     Row1    = Row2;
  724.     Row2    = Tmp_Row;
  725.  
  726.     Compute_Row((double)(i + 2) / Step_S, Row2, Step_T);
  727.  
  728.     for (j = 0; j < Step_T; j++) {
  729.  
  730.         if ( (i + j) & 1 ) {
  731.  
  732.         Generate_Face((double) i / Step_S, (double) j / Step_T,
  733.             &Row0[j], &Row1[j], &Row0[j+1], &Row1[j+1]);
  734.  
  735.         } else {
  736.  
  737.         Generate_Face((double) i / Step_S, (double) j / Step_T,
  738.             &Row1[j], &Row1[j+1], &Row0[j], &Row0[j+1]);
  739.  
  740.         }
  741.  
  742.     } /* for */
  743.  
  744.     } /* for */
  745.  
  746.     if (Verbose) fprintf(stderr, "\n");
  747.  
  748. } /* Generate_Object */
  749.  
  750. Boolean_T On_Off(Text)
  751. char    *Text;
  752. /************************************************************************/
  753. /*                                    */
  754. /* Return TRUE if text is "on" or "yes", otherwise FALSE.        */
  755. /*                                    */
  756. /************************************************************************/
  757. {
  758.     if (strcmp(Text, "on") == 0 || 
  759.         strcmp(Text, "yes") == 0) return(TRUE);
  760.  
  761.     return(FALSE);
  762.  
  763. } /* On_Off */
  764.  
  765. int    Exec_Command(Command_Line, Line_Number)
  766. char    *Command_Line;
  767. int    Line_Number;
  768. /************************************************************************/
  769. /*                                    */
  770. /* Handle special commands:                        */
  771. /*                                    */
  772. /*   #name [object_name]                        */
  773. /*     Set the object name. This name will be used for new objects.    */
  774. /*                                    */
  775. /*   #add                                */
  776. /*     Generate the surface, and add it to the current object.        */
  777. /*                                    */
  778. /*   #write [object_name]                        */
  779. /*      Write the current object to the TTDDD file and start a new     */
  780. /*    object.                                */
  781. /*                                    */
  782. /*   #generate [object_name]                        */
  783. /*     Generate the surface, add it to the current object, and write     */
  784. /*    it to the TTDDD file. This is the same as            */
  785. /*    #add followed by #write [object_name]                */
  786. /*                                    */
  787. /*   #scale scale_factor                        */
  788. /*    Change the scale factor to 'scale_factor'.            */
  789. /*                                    */
  790. /*   #phong [on|off]                            */
  791. /*   #smooth [on|off]                            */
  792. /*    Activate/Deactivate phong smoothing.                */
  793. /*                                    */
  794. /*   #color [on|off]                            */
  795. /*    Activate/deactivate generation of face color info.        */
  796. /*    The functions cr, cb and cg MUST be defined!            */
  797. /*                                    */
  798. /*   #refl [on|off]                            */
  799. /*    Activate/deactivate generation of face reflectance info.    */
  800. /*    The functions rr, rb and rg MUST be defined!            */
  801. /*                                    */
  802. /*   #trans [on|off]                            */
  803. /*    Activate/deactivate generation of face transmittance info.    */
  804. /*    The functions tr, tb and tg MUST be defined!            */
  805. /*                                    */
  806. /************************************************************************/
  807. {
  808.     char *Command;
  809.     char *Rest;
  810.     int     i;
  811.  
  812.     for (i = 0; Command_Line[i] != '\0'; i++) 
  813.                 Command_Line[i] = tolower(Command_Line[i]);
  814.  
  815.     Command = strtok(&Command_Line[1], "\n \t");
  816.     if (Command == NULL) goto SyntaxError;
  817.     Rest = strtok(NULL, "\n \t");
  818.  
  819.     if (strcmp(Command, "add") == 0) {
  820.  
  821.     Generate_Object();
  822.         Generate_Done = TRUE;
  823.  
  824.     } else if (strcmp(Command, "name") == 0) {
  825.  
  826.         if (Rest != NULL && *Rest != '\0') strcpy(Object_Name, Rest);
  827.  
  828.     } else if (strcmp(Command, "write") == 0) {
  829.  
  830.         if (Rest != NULL && *Rest != '\0') strcpy(Object_Name, Rest);
  831.  
  832.         if (Nbr_Points > 0) Write_TTDDD_Object();
  833.  
  834.     } else if (strcmp(Command, "generate") == 0) {
  835.  
  836.         if (Rest != NULL && *Rest != '\0') strcpy(Object_Name, Rest);
  837.  
  838.     Generate_Object();
  839.         Generate_Done = TRUE;
  840.         if (Nbr_Points > 0) Write_TTDDD_Object();
  841.  
  842.     } else if (strcmp(Command, "scale") == 0) {
  843.  
  844.     if (Rest == NULL) goto SyntaxError;
  845.  
  846.     Scale_Factor = atof(Rest);
  847.     if (Scale_Factor <= 0.0) {
  848.             fprintf(stderr, "Invalid scale factor in line %d:\n", 
  849.                                 Line_Number);
  850.             fprintf(stderr, "%s\n", Command_Line);
  851.             exit(1);
  852.     }
  853.         Precision = 1.0 / Scale_Factor; /* Precision of coordinates */
  854.     if (Verbose) fprintf(stderr, "New scale factor is %lf\n",
  855.                             Scale_Factor);
  856.  
  857.     } else if (strcmp(Command, "phong") == 0 || 
  858.                strcmp(Command, "smooth") == 0) {
  859.  
  860.     if (Rest == NULL) goto SyntaxError;
  861.     Phong = On_Off(Rest);
  862.  
  863.     if (Verbose) fprintf(stderr, "Phong smoothing is %s\n",
  864.             Phong ? "on" : "off");
  865.  
  866.  
  867.     } else if (strcmp(Command, "color") == 0) { 
  868.  
  869.     if (Rest == NULL) goto SyntaxError;
  870.     Compute_Color = On_Off(Rest);
  871.  
  872.     if (Verbose) fprintf(stderr, "Compute color is %s\n",
  873.             Compute_Color ? "on" : "off");
  874.  
  875.     } else if (strncmp(Command, "refl", 4) == 0) {
  876.  
  877.     if (Rest == NULL) goto SyntaxError;
  878.     Compute_Refl = On_Off(Rest);
  879.  
  880.     if (Verbose) fprintf(stderr, "Compute reflectance is %s\n",
  881.             Compute_Refl ? "on" : "off");
  882.  
  883.  
  884.     } else if (strncmp(Command, "trans", 5) == 0) {
  885.  
  886.     if (Rest == NULL) goto SyntaxError;
  887.     Compute_Trans = On_Off(Rest);
  888.  
  889.     if (Verbose) fprintf(stderr, "Compute Transmittance is %s\n",
  890.             Compute_Trans ? "on" : "off");
  891.  
  892.  
  893.     } else goto SyntaxError;
  894.  
  895.     return(0);
  896.  
  897. SyntaxError:
  898.     fprintf(stderr, "Invalid command in line %d:\n", Line_Number);
  899.     fprintf(stderr, "%s\n", Command_Line);
  900.     exit(1);
  901.  
  902.  
  903. } /* Exec_Command */
  904.  
  905. main(argc, argv)
  906. int  argc;
  907. char  *argv[];
  908. /************************************************************************/
  909. /*                                    */
  910. /*                 Main program.                */
  911. /*                                    */
  912. /************************************************************************/
  913. {
  914.     int      i;
  915.     char    *O_FileName    = NULL;
  916.  
  917.  
  918.  
  919.     if (argc == 1) Usage();
  920.  
  921.     strcpy(Object_Name, "IGENSURF");
  922.  
  923.     for (i = 1; i < argc && *argv[i] == '-'; i++) {
  924.  
  925.      switch (argv[i][1]) {
  926.     case 'C':
  927.         Compute_Color = TRUE;
  928.         break;
  929.  
  930.     case 'R':
  931.         Compute_Refl = TRUE;
  932.         break;
  933.  
  934.     case 'T':
  935.         Compute_Trans = TRUE;
  936.         break;
  937.  
  938.     case 'n':
  939.         strcpy(Object_Name, argv[++i]);
  940.         break;
  941.  
  942.     case 'S':
  943.         Scale_Factor = atof(argv[++i]);
  944.             if (Scale_Factor <= 0.0) {
  945.             fprintf(stderr, "Invalid scale factor %lf:\n", Scale_Factor);
  946.         exit(1);
  947.         }
  948.             Precision = 1.0 / Scale_Factor; /* Precision of coordinates */
  949.         break;
  950.  
  951.     case 'p':
  952.         Phong = TRUE;
  953.         break;
  954.  
  955.     case 'v':
  956.         Verbose = TRUE;
  957.         break;
  958.  
  959.     case 's':
  960.         Step_S = atoi(argv[++i]);
  961.             if (Step_S <= 0) {
  962.             fprintf(stderr, "Invalid Step_S\n", Step_S);
  963.         exit(1);
  964.         }
  965.         break;
  966.  
  967.     case 't':
  968.         Step_T = atoi(argv[++i]);
  969.             if (Step_T <= 0) {
  970.             fprintf(stderr, "Invalid Step_T\n", Step_T);
  971.         exit(1);
  972.         }
  973.         break;
  974.  
  975.     case 'e':
  976.         String_Compile(argv[++i], NULL, 0, NULL);
  977.         break;
  978.  
  979.     case 'o':
  980.         if (O_FileName != NULL) Usage();
  981.         O_FileName = argv[++i];
  982.         break;
  983.  
  984.     default:
  985.         Usage();
  986.         break;
  987.  
  988.     } /* switch */
  989.  
  990.     } /* for */
  991.  
  992.     if (Verbose) fprintf(stderr, "igensurf %s\n", Version);
  993.  
  994.     if (O_FileName == NULL) O_Stream = stdout;
  995.     else {
  996.         O_Stream = fopen(O_FileName, "w");
  997.     if (O_Stream == NULL) Error("Couldn't open the output file");
  998.     }
  999.  
  1000.     /* Define PI, step_s and step_t so that they can be used */
  1001.     /* in expressions                     */
  1002.  
  1003.     eclock = 0;
  1004.     Var_Set("PI",     ':', PI);
  1005.     Var_Set("step_s", ':', (double) Step_S);
  1006.     Var_Set("step_t", ':', (double) Step_T);
  1007.  
  1008.     while (i < argc) {
  1009.  
  1010.     if (Verbose) fprintf(stderr, "Compiling %s\n", argv[i]);
  1011.  
  1012.         File_Compile(argv[i++], Exec_Command);
  1013.  
  1014.     } /* while */
  1015.  
  1016.     if (!Generate_Done) Generate_Object();
  1017.  
  1018.     if (Nbr_Points > 0) Write_TTDDD_Object();
  1019.  
  1020.     if (O_Stream != stdout) fclose(O_Stream);
  1021.  
  1022.     if (Verbose) fprintf(stderr, "Done.\n");
  1023.  
  1024.     exit(0);
  1025.  
  1026. } /* main */
  1027.