ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgf2rad.c
(Generate patch)

Comparing ray/src/cv/mgf2rad.c (file contents):
Revision 2.5 by greg, Fri Jul 1 10:20:19 1994 UTC vs.
Revision 2.36 by greg, Fri May 23 17:02:07 2025 UTC

# Line 1 | Line 1
1 /* Copyright (c) 1994 Regents of the University of California */
2
1   #ifndef lint
2 < static char SCCSid[] = "$SunId$ LBL";
2 > static const char       RCSid[] = "$Id$";
3   #endif
6
4   /*
5   * Convert MGF (Materials and Geometry Format) to Radiance
6   */
7  
8   #include <stdio.h>
9 + #include <stdlib.h>
10   #include <math.h>
11   #include <string.h>
12 < #include "mgflib/parser.h"
12 >
13 > #include "platform.h"
14 > #include "mgf_parser.h"
15   #include "color.h"
16   #include "tmesh.h"
17 + #include "lookup.h"
18  
19   #define putv(v)         printf("%18.12g %18.12g %18.12g\n",(v)[0],(v)[1],(v)[2])
20  
21 + #define invert          (xf_context != NULL && xf_context->rev)
22 +
23 + #define SGEN_DEF        "spec*"
24 + #define SGEN_RS         "rs_spec*"
25 + #define SGEN_TD         "td_spec*"
26 + #define SGEN_TS         "ts_spec*"
27 +
28 + char    void_str[] = "void";            /* global VOIDID */
29 + char    sgen_str[16] = SGEN_DEF;        /* generic specular */
30 +
31   double  glowdist = FHUGE;               /* glow test distance */
32  
33 < double  emult = 1.;                     /* emmitter multiplier */
33 > double  emult = 1.;                     /* emitter multiplier */
34  
35 < int     r_comment(), r_cone(), r_cyl(), r_face(), r_ies(), r_ring(), r_sph();
25 < char    *material(), *object(), *addarg();
35 > FILE    *matfp;                         /* material output file */
36  
37 + int     dospectra = 0;                  /* output spectral colors? */
38  
39 < main(argc, argv)                /* convert files to stdout */
40 < int     argc;
41 < char    *argv[];
39 >
40 > extern int r_comment(int ac, char **av);
41 > extern int r_color(int ac, char **av);
42 > extern int r_cone(int ac, char **av);
43 > extern int r_cyl(int ac, char **av);
44 > extern int r_sph(int ac, char **av);
45 > extern int r_ring(int ac, char **av);
46 > extern int r_face(int ac, char **av);
47 > extern int r_ies(int ac, char **av);
48 > extern void putsided(char *mname);
49 > extern char * material(void);
50 > extern char * object(void);
51 > extern char * addarg(char *op, char *arg);
52 > extern void do_tri(char *mat, C_VERTEX *cv1, C_VERTEX *cv2, C_VERTEX *cv3, int iv);
53 > extern void cvtcolor(COLOR radrgb, C_COLOR *ciec, double intensity);
54 > extern int color_clash(int e1, int e2);
55 > extern int isgrey(COLOR rgb);
56 > extern void putrgbpat(char *pnm, COLOR rgb);
57 > extern char * specolor(COLOR radrgb, C_COLOR *ciec, double intensity);
58 >
59 >
60 > int
61 > main(
62 >        int     argc,
63 >        char    *argv[]
64 > )
65   {
66 <        int     i, rv;
66 >        int     i;
67 >
68 >        matfp = stdout;
69 >                                /* print out parser version */
70 >        printf("## Translated from MGF Version %d.%d\n", MG_VMAJOR, MG_VMINOR);
71                                  /* initialize dispatch table */
72 <        mg_ehand[MG_E_COMMENT] = r_comment;
73 <        mg_ehand[MG_E_COLOR] = c_hcolor;
74 <        mg_ehand[MG_E_CONE] = r_cone;
75 <        mg_ehand[MG_E_CMIX] = c_hcolor;
76 <        mg_ehand[MG_E_CSPEC] = c_hcolor;
77 <        mg_ehand[MG_E_CXY] = c_hcolor;
78 <        mg_ehand[MG_E_CYL] = r_cyl;
79 <        mg_ehand[MG_E_ED] = c_hmaterial;
80 <        mg_ehand[MG_E_FACE] = r_face;
81 <        mg_ehand[MG_E_IES] = r_ies;
82 <        mg_ehand[MG_E_MATERIAL] = c_hmaterial;
83 <        mg_ehand[MG_E_NORMAL] = c_hvertex;
84 <        mg_ehand[MG_E_OBJECT] = obj_handler;
85 <        mg_ehand[MG_E_POINT] = c_hvertex;
86 <        mg_ehand[MG_E_RD] = c_hmaterial;
87 <        mg_ehand[MG_E_RING] = r_ring;
88 <        mg_ehand[MG_E_RS] = c_hmaterial;
89 <        mg_ehand[MG_E_SPH] = r_sph;
90 <        mg_ehand[MG_E_TD] = c_hmaterial;
91 <        mg_ehand[MG_E_TS] = c_hmaterial;
92 <        mg_ehand[MG_E_VERTEX] = c_hvertex;
93 <        mg_ehand[MG_E_XF] = xf_handler;
72 >        mg_ehand[MG_E_COMMENT] = r_comment;     /* we pass comments */
73 >        mg_ehand[MG_E_COLOR] = c_hcolor;        /* they get color */
74 >        mg_ehand[MG_E_CONE] = r_cone;           /* we do cones */
75 >        mg_ehand[MG_E_CMIX] = c_hcolor;         /* they mix colors */
76 >        mg_ehand[MG_E_CXY] = c_hcolor;          /* they get chromaticities */
77 >        mg_ehand[MG_E_CSPEC] = r_color;         /* we get spectra */
78 >        mg_ehand[MG_E_CCT] = r_color;           /* we get color temp's */
79 >        mg_ehand[MG_E_CYL] = r_cyl;             /* we do cylinders */
80 >        mg_ehand[MG_E_ED] = c_hmaterial;        /* they get emission */
81 >        mg_ehand[MG_E_FACE] = r_face;           /* we do faces */
82 >        mg_ehand[MG_E_IES] = r_ies;             /* we do IES files */
83 >        mg_ehand[MG_E_IR] = c_hmaterial;        /* they get refractive index */
84 >        mg_ehand[MG_E_MATERIAL] = c_hmaterial;  /* they get materials */
85 >        mg_ehand[MG_E_NORMAL] = c_hvertex;      /* they get normals */
86 >        mg_ehand[MG_E_OBJECT] = obj_handler;    /* they track object names */
87 >        mg_ehand[MG_E_POINT] = c_hvertex;       /* they get points */
88 >        mg_ehand[MG_E_RD] = c_hmaterial;        /* they get diffuse refl. */
89 >        mg_ehand[MG_E_RING] = r_ring;           /* we do rings */
90 >        mg_ehand[MG_E_RS] = c_hmaterial;        /* they get specular refl. */
91 >        mg_ehand[MG_E_SIDES] = c_hmaterial;     /* they get # sides */
92 >        mg_ehand[MG_E_SPH] = r_sph;             /* we do spheres */
93 >        mg_ehand[MG_E_TD] = c_hmaterial;        /* they get diffuse trans. */
94 >        mg_ehand[MG_E_TS] = c_hmaterial;        /* they get specular trans. */
95 >        mg_ehand[MG_E_VERTEX] = c_hvertex;      /* they get vertices */
96 >        mg_ehand[MG_E_XF] = xf_handler;         /* they track transforms */
97          mg_init();              /* initialize the parser */
98 <                                        /* get options & print header */
98 >                                        /* get our options & print header */
99          printf("## %s", argv[0]);
100          for (i = 1; i < argc && argv[i][0] == '-'; i++) {
101                  printf(" %s", argv[i]);
102                  switch (argv[i][1]) {
103                  case 'g':                       /* glow distance (meters) */
104 <                        if (argv[i][2] || badarg(argc-i, argv+i, "f"))
104 >                        if (argv[i][2] || badarg(argc-i-1, argv+i+1, "f"))
105                                  goto userr;
106                          glowdist = atof(argv[++i]);
107                          printf(" %s", argv[i]);
108                          break;
109                  case 'e':                       /* emitter multiplier */
110 <                        if (argv[i][2] || badarg(argc-i, argv+i, "f"))
110 >                        if (argv[i][2] || badarg(argc-i-1, argv+i+1, "f"))
111                                  goto userr;
112                          emult = atof(argv[++i]);
113                          printf(" %s", argv[i]);
114                          break;
115 +                case 'm':                       /* materials file */
116 +                        matfp = fopen(argv[++i], "a");
117 +                        if (matfp == NULL) {
118 +                                fprintf(stderr, "%s: cannot append\n", argv[i]);
119 +                                exit(1);
120 +                        }
121 +                        printf(" %s", argv[i]);
122 +                        break;
123 +                case 's':                       /* spectral color output? */
124 +                        dospectra = !dospectra;
125 +                        break;
126                  default:
127                          goto userr;
128                  }
129          }
130          putchar('\n');
131          if (i == argc) {                /* convert stdin */
132 <                if ((rv = mg_load(NULL)) != MG_OK)
132 >                if (mg_load(NULL) != MG_OK)
133                          exit(1);
134 +                if (mg_nunknown)
135 +                        printf("## %s: %u unknown entities\n",
136 +                                        argv[0], mg_nunknown);
137          } else                          /* convert each file */
138                  for ( ; i < argc; i++) {
139                          printf("## %s %s ##############################\n",
140                                          argv[0], argv[i]);
141 <                        if ((rv = mg_load(argv[i])) != MG_OK)
141 >                        if (mg_load(argv[i]) != MG_OK)
142                                  exit(1);
143 +                        if (mg_nunknown) {
144 +                                printf("## %s %s: %u unknown entities\n",
145 +                                                argv[0], argv[i], mg_nunknown);
146 +                                mg_nunknown = 0;
147 +                        }
148                  }
149          exit(0);
150   userr:
151 <        fprintf(stderr, "Usage: %s [-g dist][-m mult] [file.mgf] ..\n",
151 >        fprintf(stderr, "Usage: %s [-s][-g dist][-e mult][-m matf] [file.mgf] ..\n",
152                          argv[0]);
153          exit(1);
154   }
155  
156  
157   int
158 < r_comment(ac, av)               /* repeat a comment verbatim */
159 < register int    ac;
160 < register char   **av;
158 > r_comment(              /* repeat a comment verbatim */
159 >        int     ac,
160 >        char    **av
161 > )
162   {
163 <        fputs("\n#", stdout);   /* use Radiance comment character */
164 <        while (--ac) {
163 >        putchar('#');           /* use Radiance comment character */
164 >        while (--ac) {                  /* pass through verbatim */
165                  putchar(' ');
166                  fputs(*++av, stdout);
167          }
# Line 110 | Line 171 | register char  **av;
171  
172  
173   int
174 < r_cone(ac, av)                  /* put out a cone */
175 < int     ac;
176 < char    **av;
174 > r_color(                /* call color handler & remember name */
175 >        int     ac,
176 >        char    **av
177 > )
178   {
179 +        int     rval = c_hcolor(ac, av);
180 +
181 +        if (rval == MG_OK)
182 +                c_ccolor->client_data = c_ccname;
183 +
184 +        return(rval);
185 + }
186 +
187 +
188 + int
189 + r_cone(                 /* put out a cone */
190 +        int     ac,
191 +        char    **av
192 + )
193 + {
194          static int      ncones;
195          char    *mat;
196          double  r1, r2;
197          C_VERTEX        *cv1, *cv2;
198          FVECT   p1, p2;
199          int     inv;
200 <
200 >                                        /* check argument count and type */
201          if (ac != 5)
202                  return(MG_EARGC);
203          if (!isflt(av[2]) || !isflt(av[4]))
204                  return(MG_ETYPE);
205 +                                        /* get the endpoint vertices */
206          if ((cv1 = c_getvert(av[1])) == NULL ||
207                          (cv2 = c_getvert(av[3])) == NULL)
208                  return(MG_EUNDEF);
209 <        xf_xfmpoint(p1, cv1->p);
209 >        xf_xfmpoint(p1, cv1->p);        /* transform endpoints */
210          xf_xfmpoint(p2, cv2->p);
211 <        r1 = xf_scale(atof(av[2]));
211 >        r1 = xf_scale(atof(av[2]));     /* scale radii */
212          r2 = xf_scale(atof(av[4]));
213 <        inv = r1 < 0.;
214 <        if (r1 == 0.) {
213 >        inv = r1 < 0.;                  /* check for inverted cone */
214 >        if (r1 == 0.) {                 /* check for illegal radii */
215                  if (r2 == 0.)
216                          return(MG_EILL);
217                  inv = r2 < 0.;
218 <        } else if (r2 != 0. && inv ^ r2 < 0.)
218 >        } else if (r2 != 0. && inv ^ (r2 < 0.))
219                  return(MG_EILL);
220          if (inv) {
221                  r1 = -r1;
222                  r2 = -r2;
223          }
224 <        if ((mat = material()) == NULL)
224 >        if ((mat = material()) == NULL) /* get material */
225                  return(MG_EBADMAT);
226 +                                        /* spit the sucker out */
227          printf("\n%s %s %sc%d\n", mat, inv ? "cup" : "cone",
228                          object(), ++ncones);
229          printf("0\n0\n8\n");
# Line 156 | Line 235 | char   **av;
235  
236  
237   int
238 < r_cyl(ac, av)                   /* put out a cylinder */
239 < int     ac;
240 < char    **av;
238 > r_cyl(                  /* put out a cylinder */
239 >        int     ac,
240 >        char    **av
241 > )
242   {
243          static int      ncyls;
244          char    *mat;
# Line 166 | Line 246 | char   **av;
246          C_VERTEX        *cv1, *cv2;
247          FVECT   p1, p2;
248          int     inv;
249 <
249 >                                        /* check argument count and type */
250          if (ac != 4)
251                  return(MG_EARGC);
252          if (!isflt(av[2]))
253                  return(MG_ETYPE);
254 +                                        /* get the endpoint vertices */
255          if ((cv1 = c_getvert(av[1])) == NULL ||
256                          (cv2 = c_getvert(av[3])) == NULL)
257                  return(MG_EUNDEF);
258 <        xf_xfmpoint(p1, cv1->p);
258 >        xf_xfmpoint(p1, cv1->p);        /* transform endpoints */
259          xf_xfmpoint(p2, cv2->p);
260 <        rad = xf_scale(atof(av[2]));
261 <        if ((inv = rad < 0.))
260 >        rad = xf_scale(atof(av[2]));    /* scale radius */
261 >        if ((inv = rad < 0.))           /* check for inverted cylinder */
262                  rad = -rad;
263 <        if ((mat = material()) == NULL)
263 >        if ((mat = material()) == NULL) /* get material */
264                  return(MG_EBADMAT);
265 +                                        /* spit out the primitive */
266          printf("\n%s %s %scy%d\n", mat, inv ? "tube" : "cylinder",
267                          object(), ++ncyls);
268          printf("0\n0\n7\n");
# Line 192 | Line 274 | char   **av;
274  
275  
276   int
277 < r_sph(ac, av)                   /* put out a sphere */
278 < int     ac;
279 < char    **av;
277 > r_sph(                  /* put out a sphere */
278 >        int     ac,
279 >        char    **av
280 > )
281   {
282          static int      nsphs;
283          char    *mat;
# Line 202 | Line 285 | char   **av;
285          C_VERTEX        *cv;
286          FVECT   cent;
287          int     inv;
288 <
288 >                                        /* check argument count and type */
289          if (ac != 3)
290                  return(MG_EARGC);
291          if (!isflt(av[2]))
292                  return(MG_ETYPE);
293 <        if ((cv = c_getvert(av[1])) == NULL)
293 >        if ((cv = c_getvert(av[1])) == NULL)    /* get center vertex */
294                  return(MG_EUNDEF);
295 <        xf_xfmpoint(cent, cv->p);
296 <        rad = xf_scale(atof(av[2]));
297 <        if ((inv = rad < 0.))
295 >        xf_xfmpoint(cent, cv->p);               /* transform center */
296 >        rad = xf_scale(atof(av[2]));            /* scale radius */
297 >        if ((inv = rad < 0.))                   /* check for inversion */
298                  rad = -rad;
299 <        if ((mat = material()) == NULL)
299 >        if ((mat = material()) == NULL)         /* get material */
300                  return(MG_EBADMAT);
301 +                                                /* spit out primitive */
302          printf("\n%s %s %ss%d\n", mat, inv ? "bubble" : "sphere",
303                          object(), ++nsphs);
304          printf("0\n0\n4 %18.12g %18.12g %18.12g %18.12g\n",
# Line 224 | Line 308 | char   **av;
308  
309  
310   int
311 < r_ring(ac, av)                  /* put out a ring */
312 < int     ac;
313 < char    **av;
311 > r_ring(                 /* put out a ring */
312 >        int     ac,
313 >        char    **av
314 > )
315   {
316          static int      nrings;
317          char    *mat;
318          double  r1, r2;
319          C_VERTEX        *cv;
320          FVECT   cent, norm;
321 <
321 >                                        /* check argument count and type */
322          if (ac != 4)
323                  return(MG_EARGC);
324          if (!isflt(av[2]) || !isflt(av[3]))
325                  return(MG_ETYPE);
326 <        if ((cv = c_getvert(av[1])) == NULL)
326 >        if ((cv = c_getvert(av[1])) == NULL)    /* get center vertex */
327                  return(MG_EUNDEF);
328 <        if (is0vect(cv->n))
328 >        if (is0vect(cv->n))                     /* make sure we have normal */
329                  return(MG_EILL);
330 <        xf_xfmpoint(cent, cv->p);
331 <        xf_rotvect(norm, cv->n);
332 <        r1 = xf_scale(atof(av[2]));
330 >        xf_xfmpoint(cent, cv->p);               /* transform center */
331 >        xf_rotvect(norm, cv->n);                /* rotate normal */
332 >        r1 = xf_scale(atof(av[2]));             /* scale radii */
333          r2 = xf_scale(atof(av[3]));
334 <        if (r1 < 0. | r2 <= r1)
334 >        if ((r1 < 0.) | (r2 <= r1))
335                  return(MG_EILL);
336 <        if ((mat = material()) == NULL)
336 >        if ((mat = material()) == NULL)         /* get material */
337                  return(MG_EBADMAT);
338 +                                                /* spit out primitive */
339          printf("\n%s ring %sr%d\n", mat, object(), ++nrings);
340          printf("0\n0\n8\n");
341          putv(cent);
# Line 260 | Line 346 | char   **av;
346  
347  
348   int
349 < r_face(ac, av)                  /* convert a face */
350 < int     ac;
351 < char    **av;
349 > r_face(                 /* convert a face */
350 >        int     ac,
351 >        char    **av
352 > )
353   {
354          static int      nfaces;
355 +        int             myi = invert;
356          char    *mat;
357 <        register int    i;
358 <        register C_VERTEX       *cv;
357 >        int     i;
358 >        C_VERTEX        *cv;
359          FVECT   v;
272        int     rv;
360  
361 +                                        /* check argument count and type */
362          if (ac < 4)
363                  return(MG_EARGC);
364 <        if ((mat = material()) == NULL)
364 >        if ((mat = material()) == NULL) /* get material */
365                  return(MG_EBADMAT);
366 <        if (ac <= 5) {                          /* check for surface normals */
366 >        if (ac <= 5) {                          /* check for smoothing */
367 >                C_VERTEX        *cva[5];
368                  for (i = 1; i < ac; i++) {
369 <                        if ((cv = c_getvert(av[i])) == NULL)
369 >                        if ((cva[i-1] = c_getvert(av[i])) == NULL)
370                                  return(MG_EUNDEF);
371 <                        if (is0vect(cv->n))
371 >                        if (is0vect(cva[i-1]->n))
372                                  break;
373                  }
374 <                if (i == ac) {                  /* break into triangles */
375 <                        do_tri(mat, av[1], av[2], av[3]);
374 >                if (i < ac)
375 >                        i = ISFLAT;
376 >                else
377 >                        i = flat_tri(cva[0]->p, cva[1]->p, cva[2]->p,
378 >                                        cva[0]->n, cva[1]->n, cva[2]->n);
379 >                if (i == DEGEN)
380 >                        return(MG_OK);          /* degenerate (error?) */
381 >                if (i == RVBENT) {
382 >                        myi = !myi;
383 >                        i = ISBENT;
384 >                } else if (i == RVFLAT) {
385 >                        myi = !myi;
386 >                        i = ISFLAT;
387 >                }
388 >                if (i == ISBENT) {              /* smoothed triangles */
389 >                        do_tri(mat, cva[0], cva[1], cva[2], myi);
390                          if (ac == 5)
391 <                                do_tri(mat, av[3], av[4], av[1]);
391 >                                do_tri(mat, cva[2], cva[3], cva[0], myi);
392                          return(MG_OK);
393                  }
394          }
395 +                                        /* spit out unsmoothed primitive */
396          printf("\n%s polygon %sf%d\n", mat, object(), ++nfaces);
397          printf("0\n0\n%d\n", 3*(ac-1));
398 <        for (i = 1; i < ac; i++) {
399 <                if ((cv = c_getvert(av[i])) == NULL)
398 >        for (i = 1; i < ac; i++) {      /* get, transform, print each vertex */
399 >                if ((cv = c_getvert(av[myi ? ac-i : i])) == NULL)
400                          return(MG_EUNDEF);
401                  xf_xfmpoint(v, cv->p);
402                  putv(v);
# Line 301 | Line 405 | char   **av;
405   }
406  
407  
408 < r_ies(ac, av)                           /* convert an IES luminaire file */
409 < int     ac;
410 < char    **av;
408 > int
409 > r_ies(                          /* convert an IES luminaire file */
410 >        int     ac,
411 >        char    **av
412 > )
413   {
414          int     xa0 = 2;
415 <        char    combuf[72];
415 >        char    combuf[128];
416          char    fname[48];
417          char    *oname;
418 <        register char   *op;
419 <        register int    i;
420 <
418 >        char    *op;
419 >        int     i;
420 >                                        /* check argument count */
421          if (ac < 2)
422                  return(MG_EARGC);
423 <        (void)strcpy(combuf, "ies2rad");
424 <        op = combuf + 7;
425 <        if (ac-xa0 >= 2 && !strcmp(av[xa0], "-m")) {
426 <                if (!isflt(av[xa0+1]))
321 <                        return(MG_ETYPE);
322 <                op = addarg(addarg(op, "-m"), av[xa0+1]);
323 <                xa0 += 2;
324 <        }
325 <        if (access(av[1], 0) == -1)
326 <                return(MG_ENOFILE);
327 <        *op++ = ' ';                    /* IES filename goes last */
328 <        (void)strcpy(op, av[1]);
329 <        system(combuf);                 /* run ies2rad */
330 <                                        /* now let's find the output file */
331 <        if ((op = strrchr(av[1], '/')) == NULL)
423 >                                        /* construct output file name */
424 >        if ((op = strrchr(av[1], '/')) != NULL)
425 >                op++;
426 >        else
427                  op = av[1];
428          (void)strcpy(fname, op);
429          if ((op = strrchr(fname, '.')) == NULL)
430                  op = fname + strlen(fname);
431          (void)strcpy(op, ".rad");
432 <        if (access(fname, 0) == -1)
433 <                return(MG_EINCL);
434 <                                        /* put out xform command */
435 <        printf("\n!xform");
432 >                                        /* see if we need to run ies2rad */
433 >        if (access(fname, 0) == -1) {
434 >                (void)strcpy(combuf, "ies2rad");/* build ies2rad command */
435 >                op = combuf + 7;                /* get -m option (first) */
436 >                if (ac-xa0 >= 2 && !strcmp(av[xa0], "-m")) {
437 >                        if (!isflt(av[xa0+1]))
438 >                                return(MG_ETYPE);
439 >                        op = addarg(addarg(op, "-m"), av[xa0+1]);
440 >                        xa0 += 2;
441 >                }
442 >                *op++ = ' ';                    /* build IES filename */
443 >                i = 0;
444 >                if (mg_file != NULL &&
445 >                                (oname = strrchr(mg_file->fname,'/')) != NULL) {
446 >                        i = oname - mg_file->fname + 1;
447 >                        (void)strcpy(op, mg_file->fname);
448 >                }
449 >                (void)strcpy(op+i, av[1]);
450 >                if (access(op, 0) == -1)        /* check for file existence */
451 >                        return(MG_ENOFILE);
452 >                system(combuf);                 /* run ies2rad */
453 >                if (access(fname, 0) == -1)     /* check success */
454 >                        return(MG_EINCL);
455 >        }
456 >        printf("\n!xform");                     /* put out xform command */
457          oname = object();
458          if (*oname) {
459                  printf(" -n ");
# Line 355 | Line 471 | char   **av;
471   }
472  
473  
474 < do_tri(mat, vn1, vn2, vn3)              /* put out smoothed triangle */
475 < char    *mat, *vn1, *vn2, *vn3;
474 > void
475 > do_tri(         /* put out smoothed triangle */
476 >        char    *mat,
477 >        C_VERTEX        *cv1,
478 >        C_VERTEX        *cv2,
479 >        C_VERTEX        *cv3,
480 >        int     iv
481 > )
482   {
483          static int      ntris;
484          BARYCCM bvecs;
485 <        FLOAT   bcoor[3][3];
486 <        C_VERTEX        *cv1, *cv2, *cv3;
485 >        RREAL   bcoor[3][3];
486 >        C_VERTEX        *cvt;
487          FVECT   v1, v2, v3;
488          FVECT   n1, n2, n3;
489 <        register int    i;
490 <                        /* the following is repeat code, so assume it's OK */
491 <        cv1 = c_getvert(vn1);
492 <        cv2 = c_getvert(vn2);
493 <        cv3 = c_getvert(vn3);
489 >        int     i;
490 >
491 >        if (iv) {                       /* swap vertex order if inverted */
492 >                cvt = cv1;
493 >                cv1 = cv3;
494 >                cv3 = cvt;
495 >        }
496          xf_xfmpoint(v1, cv1->p);
497          xf_xfmpoint(v2, cv2->p);
498          xf_xfmpoint(v3, cv3->p);
499 +                                        /* compute barycentric coords. */
500          if (comp_baryc(&bvecs, v1, v2, v3) < 0)
501                  return;                         /* degenerate triangle! */
502 <        printf("\n%s texfunc T-nor\n", mat);
502 >        printf("\n%s texfunc T-nor\n", mat);    /* put out texture */
503          printf("4 dx dy dz %s\n0\n", TCALNAME);
504          xf_rotvect(n1, cv1->n);
505          xf_rotvect(n2, cv2->n);
# Line 384 | Line 509 | char   *mat, *vn1, *vn2, *vn3;
509                  bcoor[i][1] = n2[i];
510                  bcoor[i][2] = n3[i];
511          }
512 <        put_baryc(&bvecs, bcoor, 3);
512 >        fput_baryc(&bvecs, bcoor, 3, stdout);
513 >                                                /* put out triangle */
514          printf("\nT-nor polygon %st%d\n", object(), ++ntris);
515          printf("0\n0\n9\n");
516          putv(v1);
# Line 393 | Line 519 | char   *mat, *vn1, *vn2, *vn3;
519   }
520  
521  
522 + void
523 + putsided(char *mname)           /* print out mixfunc for sided material */
524 + {
525 +        fprintf(matfp, "\nvoid mixfunc %s\n", mname);
526 +        fprintf(matfp, "4 %s void if(Rdot,1,0) .\n0\n0\n", mname);
527 + }
528 +
529 +
530   char *
531 < material()                      /* get (and print) current material */
531 > material(void)                  /* get (and print) current material */
532   {
533          char    *mname = "mat";
534 +        C_COLOR *refclr = NULL;
535 +        char    *pname;
536          COLOR   radrgb, c2;
537          double  d;
402        register int    i;
538  
539          if (c_cmname != NULL)
540                  mname = c_cmname;
# Line 408 | Line 543 | material()                     /* get (and print) current material */
543                                  /* else update output */
544          c_cmaterial->clock = 0;
545          if (c_cmaterial->ed > .1) {     /* emitter */
546 <                cvtcolor(radrgb, &c_cmaterial->ed_c,
547 <                                emult*c_cmaterial->ed/WHTEFFICACY);
546 >                pname = specolor(radrgb, &c_cmaterial->ed_c,
547 >                                emult*c_cmaterial->ed/(PI*WHTEFFICACY));
548                  if (glowdist < FHUGE) {         /* do a glow */
549 <                        printf("\nvoid glow %s\n0\n0\n", mname);
550 <                        printf("4 %f %f %f %f\n", colval(radrgb,RED),
549 >                        fprintf(matfp, "\n%s glow %s\n0\n0\n", pname, mname);
550 >                        fprintf(matfp, "4 %f %f %f %f\n", colval(radrgb,RED),
551                                          colval(radrgb,GRN),
552                                          colval(radrgb,BLU), glowdist);
553                  } else {
554 <                        printf("\nvoid light %s\n0\n0\n", mname);
555 <                        printf("3 %f %f %f\n", colval(radrgb,RED),
554 >                        fprintf(matfp, "\n%s light %s\n0\n0\n", pname, mname);
555 >                        fprintf(matfp, "3 %f %f %f\n", colval(radrgb,RED),
556                                          colval(radrgb,GRN),
557                                          colval(radrgb,BLU));
558                  }
# Line 425 | Line 560 | material()                     /* get (and print) current material */
560          }
561          d = c_cmaterial->rd + c_cmaterial->td +
562                          c_cmaterial->rs + c_cmaterial->ts;
563 <        if (d <= 0. | d >= 1.)
563 >        if ((d < 0.) | (d > 1.))
564                  return(NULL);
565 +                                        /* check for glass/dielectric */
566 +        if (c_cmaterial->nr > 1.1 &&
567 +                        c_cmaterial->ts > .25 && c_cmaterial->rs <= .125 &&
568 +                        c_cmaterial->td <= .01 && c_cmaterial->rd <= .01 &&
569 +                        c_cmaterial->rs_a <= .01 && c_cmaterial->ts_a <= .01) {
570 +                cvtcolor(radrgb, &c_cmaterial->ts_c,
571 +                                c_cmaterial->ts + c_cmaterial->rs);
572 +                if (c_cmaterial->sided) {               /* dielectric */
573 +                        colval(radrgb,RED) = pow(colval(radrgb,RED),
574 +                                                        1./C_1SIDEDTHICK);
575 +                        colval(radrgb,GRN) = pow(colval(radrgb,GRN),
576 +                                                        1./C_1SIDEDTHICK);
577 +                        colval(radrgb,BLU) = pow(colval(radrgb,BLU),
578 +                                                        1./C_1SIDEDTHICK);
579 +                        fprintf(matfp, "\nvoid dielectric %s\n0\n0\n", mname);
580 +                        fprintf(matfp, "5 %g %g %g %f 0\n", colval(radrgb,RED),
581 +                                        colval(radrgb,GRN), colval(radrgb,BLU),
582 +                                        c_cmaterial->nr);
583 +                        return(mname);
584 +                }
585 +                                                        /* glass */
586 +                fprintf(matfp, "\nvoid glass %s\n0\n0\n", mname);
587 +                fprintf(matfp, "4 %f %f %f %f\n", colval(radrgb,RED),
588 +                                colval(radrgb,GRN), colval(radrgb,BLU),
589 +                                c_cmaterial->nr);
590 +                return(mname);
591 +        }
592 +                                        /* check for WGMDfunc */
593 +        if (((c_cmaterial->rs > .02) & (c_cmaterial->ts > .02) &&
594 +                        fabs(c_cmaterial->rs_a - c_cmaterial->ts_a) > .02) ||
595 +                        ((c_cmaterial->rs > .05) & (c_cmaterial->rd > .05) &&
596 +                                !c_isgrey(&c_cmaterial->rs_c) &&
597 +                                !c_equiv(&c_cmaterial->rd_c, &c_cmaterial->rs_c)) ||
598 +                        color_clash(MG_E_TS, MG_E_TD) ||
599 +                        color_clash(MG_E_TD, MG_E_RD) ||
600 +                        color_clash(MG_E_RD, MG_E_TS)) {
601 +                COLOR   rs_rgb, ts_rgb, td_rgb; /* separate modifier paths */
602 +                char    rs_pname[128], ts_pname[128], td_pname[128];
603 +                strcpy(sgen_str, SGEN_RS);
604 +                strcpy(rs_pname, specolor(rs_rgb, &c_cmaterial->rs_c, c_cmaterial->rs));
605 +                strcpy(sgen_str, SGEN_TS);
606 +                strcpy(ts_pname, specolor(ts_rgb, &c_cmaterial->ts_c, c_cmaterial->ts));
607 +                strcpy(sgen_str, SGEN_TD);
608 +                strcpy(td_pname, specolor(td_rgb, &c_cmaterial->td_c, c_cmaterial->td));
609 +                strcpy(sgen_str, SGEN_DEF);
610 +                pname = specolor(radrgb, &c_cmaterial->rd_c, c_cmaterial->rd);
611 +                if (!strcmp(rs_pname, void_str) && !isgrey(rs_rgb)) {
612 +                        putrgbpat(strcpy(rs_pname,"rs_rgb*"), rs_rgb);
613 +                        colval(rs_rgb,GRN) = 1;
614 +                }
615 +                if (!strcmp(ts_pname, void_str) && !isgrey(ts_rgb)) {
616 +                        putrgbpat(strcpy(ts_pname,"ts_rgb*"), ts_rgb);
617 +                        colval(ts_rgb,GRN) = 1;
618 +                }
619 +                fprintf(matfp, "\n%s WGMDfunc %s\n", pname, mname);
620 +                fprintf(matfp, "13\t%s %f %f %f\n", rs_pname, colval(rs_rgb,GRN),
621 +                                c_cmaterial->rs_a, c_cmaterial->rs_a);
622 +                fprintf(matfp, "\t%s %f %f %f\n", ts_pname, colval(ts_rgb,GRN),
623 +                                c_cmaterial->ts_a, c_cmaterial->ts_a);
624 +                fprintf(matfp, "\t%s\n\t0 0 1 .\n0\n", td_pname);
625 +                fprintf(matfp, "9\t%f %f %f\n", colval(radrgb,RED),
626 +                                colval(radrgb,GRN), colval(radrgb,BLU));
627 +                fprintf(matfp, "\t%f %f %f\n", colval(radrgb,RED),
628 +                                colval(radrgb,GRN), colval(radrgb,BLU));
629 +                fprintf(matfp, "\t%f %f %f\n", colval(td_rgb,RED),
630 +                                colval(td_rgb,GRN), colval(td_rgb,BLU));
631 +                if (c_cmaterial->sided)
632 +                        putsided(mname);
633 +                return(mname);
634 +        }
635                                          /* check for trans */
636 <        if (c_cmaterial->td > .01 || c_cmaterial->ts > .01) {
637 <                double  ts, a5, a6;
433 <
434 <                ts = sqrt(c_cmaterial->ts);     /* because we use 2 sides */
636 >        if (c_cmaterial->td + c_cmaterial->ts > .01) {
637 >                double  a5, a6;
638                                                  /* average colors */
639 <                d = c_cmaterial->rd + c_cmaterial->td + ts;
639 >                d = c_cmaterial->rd + c_cmaterial->td + c_cmaterial->ts;
640                  cvtcolor(radrgb, &c_cmaterial->rd_c, c_cmaterial->rd/d);
641                  cvtcolor(c2, &c_cmaterial->td_c, c_cmaterial->td/d);
642                  addcolor(radrgb, c2);
643 <                cvtcolor(c2, &c_cmaterial->ts_c, ts/d);
643 >                cvtcolor(c2, &c_cmaterial->ts_c, c_cmaterial->ts/d);
644                  addcolor(radrgb, c2);
645 <                if (c_cmaterial->rs + ts > .0001)
645 >                if (c_cmaterial->rs + c_cmaterial->ts > .0001)
646                          a5 = (c_cmaterial->rs*c_cmaterial->rs_a +
647 <                                        ts*.5*c_cmaterial->ts_a) /
648 <                                        (c_cmaterial->rs + ts);
649 <                a6 = (c_cmaterial->td + ts) /
650 <                                (c_cmaterial->rd + c_cmaterial->td + ts);
651 <                if (a6 < .999) {
647 >                                        c_cmaterial->ts*c_cmaterial->ts_a) /
648 >                                        (c_cmaterial->rs + c_cmaterial->ts);
649 >                a6 = (c_cmaterial->td + c_cmaterial->ts) /
650 >                                (c_cmaterial->rd + c_cmaterial->td + c_cmaterial->ts);
651 >                if (a6 < .999)
652                          d = c_cmaterial->rd/(1. - c_cmaterial->rs)/(1. - a6);
653 <                        scalecolor(radrgb, d);
654 <                }
655 <                printf("\nvoid trans %s\n0\n0\n", mname);
656 <                printf("7 %f %f %f\n", colval(radrgb,RED),
653 >                else
654 >                        d = c_cmaterial->td + c_cmaterial->ts;
655 >                scalecolor(radrgb, d);
656 >                fprintf(matfp, "\nvoid trans %s\n0\n0\n", mname);
657 >                fprintf(matfp, "7 %f %f %f\n", colval(radrgb,RED),
658                                  colval(radrgb,GRN), colval(radrgb,BLU));
659 <                printf("\t%f %f %f %f\n", c_cmaterial->rs, a5, a6,
660 <                                ts/(ts + c_cmaterial->td));
659 >                fprintf(matfp, "\t%f %f %f %f\n", c_cmaterial->rs, a5, a6,
660 >                                c_cmaterial->ts/(c_cmaterial->ts + c_cmaterial->td));
661 >                if (c_cmaterial->sided)
662 >                        putsided(mname);
663                  return(mname);
664          }
665                                          /* check for plastic */
666 <        if (c_cmaterial->rs < .01 || c_isgrey(&c_cmaterial->rs_c)) {
667 <                if (c_cmaterial->rs > .999)
668 <                        cvtcolor(radrgb, &c_cmaterial->rd_c, 1.);
463 <                else
464 <                        cvtcolor(radrgb, &c_cmaterial->rd_c,
666 >        if (c_cmaterial->rs < .1 && (c_cmaterial->rs < .1*c_cmaterial->rd ||
667 >                                        c_isgrey(&c_cmaterial->rs_c))) {
668 >                pname = specolor(radrgb, &c_cmaterial->rd_c,
669                                          c_cmaterial->rd/(1.-c_cmaterial->rs));
670 <                printf("\nvoid plastic %s\n0\n0\n", mname);
671 <                printf("5 %f %f %f %f %f\n", colval(radrgb,RED),
670 >                fprintf(matfp, "\n%s plastic %s\n0\n0\n", pname, mname);
671 >                fprintf(matfp, "5 %f %f %f %f %f\n", colval(radrgb,RED),
672                                  colval(radrgb,GRN), colval(radrgb,BLU),
673                                  c_cmaterial->rs, c_cmaterial->rs_a);
674 +                if (c_cmaterial->sided)
675 +                        putsided(mname);
676                  return(mname);
677          }
678                                          /* else it's metal */
679 <        d = c_cmaterial->rd + c_cmaterial->rs;  /* average colors */
680 <        cvtcolor(radrgb, &c_cmaterial->rd_c, c_cmaterial->rd/d);
681 <        cvtcolor(c2, &c_cmaterial->rs_c, c_cmaterial->rs/d);
682 <        addcolor(radrgb, c2);
683 <        if (c_cmaterial->rs < .999) {
684 <                d = c_cmaterial->rd/(1. - c_cmaterial->rs);
685 <                scalecolor(radrgb, d);
679 >                                                /* compute color */
680 >        if (c_equiv(&c_cmaterial->rd_c, &c_cmaterial->rs_c)) {
681 >                pname = specolor(radrgb, &c_cmaterial->rs_c, c_cmaterial->rs+c_cmaterial->rd);
682 >        } else if (c_cmaterial->rd <= .05f) {
683 >                pname = specolor(radrgb, &c_cmaterial->rs_c, c_cmaterial->rs);
684 >                cvtcolor(c2, &c_cmaterial->rd_c, c_cmaterial->rd);
685 >                addcolor(radrgb, c2);
686 >        } else {
687 >                pname = "void";
688 >                cvtcolor(radrgb, &c_cmaterial->rd_c, c_cmaterial->rd);
689 >                cvtcolor(c2, &c_cmaterial->rs_c, c_cmaterial->rs);
690 >                addcolor(radrgb, c2);
691          }
692 <        printf("\nvoid metal %s\n0\n0\n", mname);
693 <        printf("5 %f %f %f %f %f\n", colval(radrgb,RED),
692 >        fprintf(matfp, "\n%s metal %s\n0\n0\n", pname, mname);
693 >        fprintf(matfp, "5 %f %f %f %f %f\n", colval(radrgb,RED),
694                          colval(radrgb,GRN), colval(radrgb,BLU),
695 <                        c_cmaterial->rs, c_cmaterial->rs_a);
695 >                        c_cmaterial->rs/(c_cmaterial->rd + c_cmaterial->rs),
696 >                        c_cmaterial->rs_a);
697 >        if (c_cmaterial->sided)
698 >                putsided(mname);
699          return(mname);
700   }
701  
702  
703 < cvtcolor(radrgb, ciec, intensity)       /* convert a CIE color to Radiance */
704 < COLOR   radrgb;
705 < register C_COLOR        *ciec;
706 < double  intensity;
703 > void
704 > cvtcolor(       /* convert a CIE XYZ color to RGB */
705 >        COLOR   radrgb,
706 >        C_COLOR *ciec,
707 >        double  intensity
708 > )
709   {
710 <        static COLOR    ciexyz;
710 >        COLOR   ciexyz;
711  
712 +        if (intensity <= 0) {
713 +                setcolor(radrgb, 0, 0, 0);
714 +                return;
715 +        }
716          c_ccvt(ciec, C_CSXY);           /* get xy representation */
717          ciexyz[1] = intensity;
718          ciexyz[0] = ciec->cx/ciec->cy*ciexyz[1];
# Line 501 | Line 721 | double intensity;
721   }
722  
723  
724 + int color_clash(        /* do non-zero material components clash? */
725 +        int e1,
726 +        int e2
727 + )
728 + {
729 +        C_COLOR *c1;
730 +
731 +        if (e1 == e2)
732 +                return(0);
733 +        switch (e1) {
734 +        case MG_E_RD:
735 +                if (c_cmaterial->rd <= .01) return(0);
736 +                c1 = &c_cmaterial->rd_c;
737 +                break;
738 +        case MG_E_RS:
739 +                if (c_cmaterial->rs <= .01) return(0);
740 +                c1 = &c_cmaterial->rs_c;
741 +                break;
742 +        case MG_E_TD:
743 +                if (c_cmaterial->td <= .01) return(0);
744 +                c1 = &c_cmaterial->td_c;
745 +                break;
746 +        case MG_E_TS:
747 +                if (c_cmaterial->ts <= .01) return(0);
748 +                c1 = &c_cmaterial->ts_c;
749 +                break;
750 +        default:
751 +                return(0);
752 +        }
753 +        switch (e2) {
754 +        case MG_E_RD:
755 +                if (c_cmaterial->rd <= .01) return(0);
756 +                return(!c_equiv(c1, &c_cmaterial->rd_c));
757 +        case MG_E_RS:
758 +                if (c_cmaterial->rs <= .01) return(0);
759 +                return(!c_equiv(c1, &c_cmaterial->rs_c));
760 +        case MG_E_TD:
761 +                if (c_cmaterial->td <= .01) return(0);
762 +                return(!c_equiv(c1, &c_cmaterial->td_c));
763 +        case MG_E_TS:
764 +                if (c_cmaterial->ts <= .01) return(0);
765 +                return(!c_equiv(c1, &c_cmaterial->ts_c));
766 +        }
767 +        return(0);
768 + }
769 +
770 +
771 + static int      /* new spectrum definition? */
772 + newspecdef(C_COLOR *spc)
773 + {
774 +        static LUTAB    spc_tab = LU_SINIT(NULL,free);
775 +        LUENT   *lp = lu_find(&spc_tab, (const char *)spc->client_data);
776 +
777 +        if (lp == NULL)                 /* should never happen */
778 +                return(1);
779 +        if (lp->data == NULL) {         /* new entry */
780 +                lp->key = (char *)spc->client_data;
781 +                lp->data = (char *)malloc(sizeof(C_COLOR));
782 +        } else if (c_equiv(spc, (C_COLOR *)lp->data))
783 +                return(0);              /* unchanged */
784 +
785 +        if (lp->data != NULL)           /* else remember if we can */
786 +                *(C_COLOR *)lp->data = *spc;
787 +        return(1);                      /* good as new */
788 + }
789 +
790 +
791   char *
792 < object()                        /* return current object name */
792 > specolor(       /* check if color has spectra and output accordingly */
793 >        COLOR   radrgb,
794 >        C_COLOR *clr,
795 >        double  intensity
796 > )
797   {
798 +        static char     spname[128];
799 +        double  mult;
800 +        int     cbeg, cend, i;
801 +
802 +        if (!dospectra | !(clr->flags & C_CDSPEC) | (intensity <= FTINY)) {
803 +                cvtcolor(radrgb, clr, intensity);
804 +                return(void_str);               /* just use RGB */
805 +        }
806 +        setcolor(radrgb, intensity, intensity, intensity);
807 +        for (cbeg = 0; cbeg < C_CNSS; cbeg++)   /* trim zeros off beginning */
808 +                if (clr->ssamp[cbeg])
809 +                        break;
810 +        if (cbeg >= C_CNSS)                     /* should never happen! */
811 +                return(void_str);
812 +        if (clr->client_data != NULL) {         /* get name if available */
813 +                strcpy(spname, (char *)clr->client_data);
814 +                strcat(spname, "*");            /* make sure it's special */
815 +                if (!newspecdef(clr))           /* output already? */
816 +                        return(spname);
817 +        } else
818 +                strcpy(spname, sgen_str);
819 +        c_ccvt(clr, C_CSEFF);                   /* else output spectrum prim */
820 +        for (cend = 0; !clr->ssamp[C_CNSS-1-cend]; cend++)
821 +                ;                               /* trim zeros off end */
822 +        fprintf(matfp, "\nvoid spectrum %s\n0\n0\n", spname);
823 +        fprintf(matfp, "%d %d %d", C_CNSS+2-cbeg-cend,
824 +                C_CMINWL+cbeg*C_CWLI, C_CMAXWL-cend*C_CWLI);
825 +        mult = (C_CNSS*c_dfcolor.eff)/(clr->ssum*clr->eff);
826 +        for (i = cbeg; i < C_CNSS-cend; i++) {
827 +                if (!((i-cbeg+1)%6)) fputc('\n', matfp);
828 +                fprintf(matfp, "\t%.5f", clr->ssamp[i]*mult);
829 +        }
830 +        fputc('\n', matfp);
831 +        return(spname);
832 + }
833 +
834 +
835 + int
836 + isgrey(                         /* is RGB close match to grey? */
837 +        COLOR rgb
838 + )
839 + {
840 +        const double    yv = bright(rgb);
841 +        double          diff2 = 0;
842 +        int             i;
843 +
844 +        for (i = 3; i--; ) {
845 +                double  d = yv - colval(rgb,i);
846 +                diff2 += d*d;
847 +        }
848 +        return(diff2 <= yv*yv*0.0025);
849 + }
850 +
851 +
852 + void
853 + putrgbpat(                      /* put out RGB pattern with given name */
854 +        char *pnm,
855 +        COLOR rgb
856 + )
857 + {
858 +        fprintf(matfp, "\nvoid colorfunc %s\n", pnm);
859 +        fprintf(matfp, "4 %f %f %f .\n0\n0\n", colval(rgb,RED),
860 +                        colval(rgb,GRN), colval(rgb,BLU));
861 + }
862 +
863 +
864 + char *
865 + object(void)                    /* return current object name */
866 + {
867          static char     objbuf[64];
868 <        register int    i;
869 <        register char   *cp;
868 >        int     i;
869 >        char    *cp;
870          int     len;
871 <
871 >                                                /* tracked by obj_handler */
872          i = obj_nnames - sizeof(objbuf)/16;
873          if (i < 0)
874                  i = 0;
# Line 524 | Line 884 | object()                       /* return current object name */
884  
885  
886   char *
887 < addarg(op, arg)                         /* add argument and advance pointer */
888 < register char   *op, *arg;
887 > addarg(                         /* add argument and advance pointer */
888 >        char *op,
889 >        char *arg
890 > )
891   {
892          *op = ' ';
893 <        while (*++op = *arg++)
893 >        while ( (*++op = *arg++) )
894                  ;
895          return(op);
896   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines