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