ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/context.c
Revision: 1.10
Committed: Sat Jun 25 19:31:14 1994 UTC (29 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.9: +16 -13 lines
Log Message:
fixed bugs made worse by last change

File Contents

# User Rev Content
1 greg 1.1 /* Copyright (c) 1994 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * Context handlers
9     */
10    
11     #include <stdio.h>
12 greg 1.2 #include <math.h>
13 greg 1.1 #include <string.h>
14     #include "parser.h"
15     #include "lookup.h"
16    
17     /* default context values */
18     static C_COLOR c_dfcolor = C_DEFCOLOR;
19     static C_MATERIAL c_dfmaterial = C_DEFMATERIAL;
20     static C_VERTEX c_dfvertex = C_DEFVERTEX;
21    
22     /* the unnamed contexts */
23     static C_COLOR c_uncolor = C_DEFCOLOR;
24     static C_MATERIAL c_unmaterial = C_DEFMATERIAL;
25     static C_VERTEX c_unvertex = C_DEFVERTEX;
26    
27     /* the current contexts */
28     C_COLOR *c_ccolor = &c_uncolor;
29     C_MATERIAL *c_cmaterial = &c_unmaterial;
30     C_VERTEX *c_cvertex = &c_unvertex;
31    
32 greg 1.3 static LUTAB clr_tab = LU_SINIT(free,free); /* color lookup table */
33     static LUTAB mat_tab = LU_SINIT(free,free); /* material lookup table */
34     static LUTAB vtx_tab = LU_SINIT(free,free); /* vertex lookup table */
35 greg 1.1
36 greg 1.5 /* CIE 1931 Standard Observer */
37     static C_COLOR cie_xf = C_CIEX;
38     static C_COLOR cie_yf = C_CIEY;
39     static C_COLOR cie_zf = C_CIEZ;
40 greg 1.1
41 greg 1.5 static int setspectrum();
42     static void mixcolors();
43    
44    
45 greg 1.1 int
46     c_hcolor(ac, av) /* handle color entity */
47     int ac;
48     register char **av;
49     {
50 greg 1.5 double w, wsum;
51     register int i;
52 greg 1.10 char *nm;
53 greg 1.1 register LUENT *lp;
54    
55     switch (mg_entity(av[0])) {
56     case MG_E_COLOR: /* get/set color context */
57 greg 1.4 if (ac > 4)
58     return(MG_EARGC);
59 greg 1.1 if (ac == 1) { /* set unnamed color context */
60     c_uncolor = c_dfcolor;
61     c_ccolor = &c_uncolor;
62     return(MG_OK);
63     }
64     lp = lu_find(&clr_tab, av[1]); /* lookup context */
65     if (lp == NULL)
66     return(MG_EMEM);
67 greg 1.9 c_ccolor = (C_COLOR *)lp->data;
68 greg 1.1 if (ac == 2) { /* reestablish previous context */
69 greg 1.9 if (c_ccolor == NULL)
70 greg 1.1 return(MG_EUNDEF);
71     return(MG_OK);
72     }
73     if (av[2][0] != '=' || av[2][1])
74     return(MG_ETYPE);
75 greg 1.9 if (c_ccolor == NULL) { /* create new color context */
76 greg 1.1 lp->key = (char *)malloc(strlen(av[1])+1);
77     if (lp->key == NULL)
78     return(MG_EMEM);
79     strcpy(lp->key, av[1]);
80     lp->data = (char *)malloc(sizeof(C_COLOR));
81     if (lp->data == NULL)
82     return(MG_EMEM);
83 greg 1.9 c_ccolor = (C_COLOR *)lp->data;
84     c_ccolor->clock = 0;
85 greg 1.1 }
86 greg 1.10 nm = lp->key;
87     i = c_ccolor->clock;
88 greg 1.1 if (ac == 3) { /* use default template */
89     *c_ccolor = c_dfcolor;
90 greg 1.10 c_ccolor->name = nm;
91 greg 1.9 c_ccolor->clock = i + 1;
92 greg 1.1 return(MG_OK);
93     }
94     lp = lu_find(&clr_tab, av[3]); /* lookup template */
95     if (lp == NULL)
96     return(MG_EMEM);
97     if (lp->data == NULL)
98     return(MG_EUNDEF);
99     *c_ccolor = *(C_COLOR *)lp->data;
100 greg 1.10 c_ccolor->name = nm;
101 greg 1.9 c_ccolor->clock = i + 1;
102 greg 1.1 return(MG_OK);
103     case MG_E_CXY: /* assign CIE XY value */
104     if (ac != 3)
105     return(MG_EARGC);
106     if (!isflt(av[1]) || !isflt(av[2]))
107     return(MG_ETYPE);
108     c_ccolor->cx = atof(av[1]);
109     c_ccolor->cy = atof(av[2]);
110 greg 1.5 c_ccolor->flags = C_CDXY|C_CSXY;
111 greg 1.1 if (c_ccolor->cx < 0. | c_ccolor->cy < 0. |
112     c_ccolor->cx + c_ccolor->cy > 1.)
113     return(MG_EILL);
114 greg 1.8 c_ccolor->clock++;
115 greg 1.1 return(MG_OK);
116 greg 1.5 case MG_E_CSPEC: /* assign spectral values */
117     if (ac < 5)
118     return(MG_EARGC);
119     if (!isint(av[1]) || !isint(av[2]))
120     return(MG_ETYPE);
121     return(setspectrum(c_ccolor, atoi(av[1]), atoi(av[2]),
122     ac-3, av+3));
123     case MG_E_CMIX: /* mix colors */
124     if (ac < 5 || (ac-1)%2)
125     return(MG_EARGC);
126     if (!isflt(av[1]))
127     return(MG_ETYPE);
128     wsum = atof(av[1]);
129     if (wsum < 0.)
130     return(MG_EILL);
131     if ((lp = lu_find(&clr_tab, av[2])) == NULL)
132     return(MG_EMEM);
133     if (lp->data == NULL)
134     return(MG_EUNDEF);
135     *c_ccolor = *(C_COLOR *)lp->data;
136     for (i = 3; i < ac; i += 2) {
137     if (!isflt(av[i]))
138     return(MG_ETYPE);
139     w = atof(av[i]);
140     if (w < 0.)
141     return(MG_EILL);
142     if ((lp = lu_find(&clr_tab, av[i+1])) == NULL)
143     return(MG_EMEM);
144     if (lp->data == NULL)
145     return(MG_EUNDEF);
146     mixcolors(c_ccolor, wsum, c_ccolor,
147     w, (C_COLOR *)lp->data);
148     wsum += w;
149     }
150 greg 1.10 c_ccolor->clock++;
151 greg 1.5 return(MG_OK);
152 greg 1.1 }
153     return(MG_EUNK);
154     }
155    
156    
157     int
158     c_hmaterial(ac, av) /* handle material entity */
159     int ac;
160     register char **av;
161     {
162 greg 1.9 int i;
163 greg 1.10 char *nm;
164 greg 1.1 register LUENT *lp;
165    
166     switch (mg_entity(av[0])) {
167     case MG_E_MATERIAL: /* get/set material context */
168 greg 1.4 if (ac > 4)
169     return(MG_EARGC);
170 greg 1.1 if (ac == 1) { /* set unnamed material context */
171     c_unmaterial = c_dfmaterial;
172     c_cmaterial = &c_unmaterial;
173     return(MG_OK);
174     }
175     lp = lu_find(&mat_tab, av[1]); /* lookup context */
176     if (lp == NULL)
177     return(MG_EMEM);
178 greg 1.9 c_cmaterial = (C_MATERIAL *)lp->data;
179 greg 1.1 if (ac == 2) { /* reestablish previous context */
180 greg 1.9 if (c_cmaterial == NULL)
181 greg 1.1 return(MG_EUNDEF);
182     return(MG_OK);
183     }
184     if (av[2][0] != '=' || av[2][1])
185     return(MG_ETYPE);
186 greg 1.9 if (c_cmaterial == NULL) { /* create new material */
187 greg 1.1 lp->key = (char *)malloc(strlen(av[1])+1);
188     if (lp->key == NULL)
189     return(MG_EMEM);
190     strcpy(lp->key, av[1]);
191     lp->data = (char *)malloc(sizeof(C_MATERIAL));
192     if (lp->data == NULL)
193     return(MG_EMEM);
194 greg 1.9 c_cmaterial = (C_MATERIAL *)lp->data;
195     c_cmaterial->clock = 0;
196 greg 1.1 }
197 greg 1.10 nm = lp->key;
198     i = c_cmaterial->clock;
199 greg 1.1 if (ac == 3) { /* use default template */
200     *c_cmaterial = c_dfmaterial;
201 greg 1.10 c_cmaterial->name = nm;
202 greg 1.9 c_cmaterial->clock = i + 1;
203 greg 1.1 return(MG_OK);
204     }
205     lp = lu_find(&mat_tab, av[3]); /* lookup template */
206     if (lp == NULL)
207     return(MG_EMEM);
208     if (lp->data == NULL)
209     return(MG_EUNDEF);
210     *c_cmaterial = *(C_MATERIAL *)lp->data;
211 greg 1.10 c_cmaterial->name = nm;
212 greg 1.9 c_cmaterial->clock = i + 1;
213 greg 1.1 return(MG_OK);
214     case MG_E_RD: /* set diffuse reflectance */
215     if (ac != 2)
216     return(MG_EARGC);
217     if (!isflt(av[1]))
218     return(MG_ETYPE);
219     c_cmaterial->rd = atof(av[1]);
220     if (c_cmaterial->rd < 0. | c_cmaterial->rd > 1.)
221     return(MG_EILL);
222     c_cmaterial->rd_c = *c_ccolor;
223 greg 1.2 c_cmaterial->clock++;
224 greg 1.1 return(MG_OK);
225     case MG_E_ED: /* set diffuse emittance */
226     if (ac != 2)
227     return(MG_EARGC);
228     if (!isflt(av[1]))
229     return(MG_ETYPE);
230     c_cmaterial->ed = atof(av[1]);
231     if (c_cmaterial->ed < 0.)
232     return(MG_EILL);
233     c_cmaterial->ed_c = *c_ccolor;
234 greg 1.2 c_cmaterial->clock++;
235 greg 1.1 return(MG_OK);
236     case MG_E_TD: /* set diffuse transmittance */
237     if (ac != 2)
238     return(MG_EARGC);
239     if (!isflt(av[1]))
240     return(MG_ETYPE);
241     c_cmaterial->td = atof(av[1]);
242     if (c_cmaterial->td < 0. | c_cmaterial->td > 1.)
243     return(MG_EILL);
244     c_cmaterial->td_c = *c_ccolor;
245 greg 1.8 c_cmaterial->clock++;
246 greg 1.1 return(MG_OK);
247     case MG_E_RS: /* set specular reflectance */
248     if (ac != 3)
249     return(MG_EARGC);
250     if (!isflt(av[1]) || !isflt(av[2]))
251     return(MG_ETYPE);
252     c_cmaterial->rs = atof(av[1]);
253     c_cmaterial->rs_a = atof(av[2]);
254     if (c_cmaterial->rs < 0. | c_cmaterial->rs > 1. |
255     c_cmaterial->rs_a < 0.)
256     return(MG_EILL);
257     c_cmaterial->rs_c = *c_ccolor;
258 greg 1.2 c_cmaterial->clock++;
259 greg 1.1 return(MG_OK);
260     case MG_E_TS: /* set specular transmittance */
261     if (ac != 3)
262     return(MG_EARGC);
263     if (!isflt(av[1]) || !isflt(av[2]))
264     return(MG_ETYPE);
265     c_cmaterial->ts = atof(av[1]);
266     c_cmaterial->ts_a = atof(av[2]);
267     if (c_cmaterial->ts < 0. | c_cmaterial->ts > 1. |
268     c_cmaterial->ts_a < 0.)
269     return(MG_EILL);
270     c_cmaterial->ts_c = *c_ccolor;
271 greg 1.2 c_cmaterial->clock++;
272 greg 1.1 return(MG_OK);
273     }
274     return(MG_EUNK);
275     }
276    
277    
278     int
279     c_hvertex(ac, av) /* handle a vertex entity */
280     int ac;
281     register char **av;
282     {
283 greg 1.9 int i;
284 greg 1.10 char *nm;
285 greg 1.1 register LUENT *lp;
286    
287     switch (mg_entity(av[0])) {
288     case MG_E_VERTEX: /* get/set vertex context */
289 greg 1.4 if (ac > 4)
290     return(MG_EARGC);
291 greg 1.1 if (ac == 1) { /* set unnamed vertex context */
292     c_unvertex = c_dfvertex;
293     c_cvertex = &c_unvertex;
294     return(MG_OK);
295     }
296     lp = lu_find(&vtx_tab, av[1]); /* lookup context */
297     if (lp == NULL)
298     return(MG_EMEM);
299 greg 1.9 c_cvertex = (C_VERTEX *)lp->data;
300 greg 1.1 if (ac == 2) { /* reestablish previous context */
301 greg 1.9 if (c_cvertex == NULL)
302 greg 1.1 return(MG_EUNDEF);
303     return(MG_OK);
304     }
305     if (av[2][0] != '=' || av[2][1])
306     return(MG_ETYPE);
307 greg 1.9 if (c_cvertex == NULL) { /* create new vertex context */
308 greg 1.1 lp->key = (char *)malloc(strlen(av[1])+1);
309     if (lp->key == NULL)
310     return(MG_EMEM);
311     strcpy(lp->key, av[1]);
312     lp->data = (char *)malloc(sizeof(C_VERTEX));
313     if (lp->data == NULL)
314     return(MG_EMEM);
315 greg 1.9 c_cvertex = (C_VERTEX *)lp->data;
316 greg 1.1 }
317 greg 1.10 nm = lp->key;
318     i = c_cvertex->clock;
319 greg 1.1 if (ac == 3) { /* use default template */
320     *c_cvertex = c_dfvertex;
321 greg 1.10 c_cvertex->name = nm;
322 greg 1.9 c_cvertex->clock = i + 1;
323 greg 1.1 return(MG_OK);
324     }
325     lp = lu_find(&vtx_tab, av[3]); /* lookup template */
326     if (lp == NULL)
327     return(MG_EMEM);
328     if (lp->data == NULL)
329     return(MG_EUNDEF);
330     *c_cvertex = *(C_VERTEX *)lp->data;
331 greg 1.10 c_cvertex->name = nm;
332 greg 1.9 c_cvertex->clock = i + 1;
333 greg 1.1 return(MG_OK);
334     case MG_E_POINT: /* set point */
335     if (ac != 4)
336     return(MG_EARGC);
337     if (!isflt(av[1]) || !isflt(av[2]) || !isflt(av[3]))
338     return(MG_ETYPE);
339     c_cvertex->p[0] = atof(av[1]);
340     c_cvertex->p[1] = atof(av[2]);
341     c_cvertex->p[2] = atof(av[3]);
342 greg 1.8 c_cvertex->clock++;
343 greg 1.1 return(MG_OK);
344     case MG_E_NORMAL: /* set normal */
345     if (ac != 4)
346     return(MG_EARGC);
347     if (!isflt(av[1]) || !isflt(av[2]) || !isflt(av[3]))
348     return(MG_ETYPE);
349     c_cvertex->n[0] = atof(av[1]);
350     c_cvertex->n[1] = atof(av[2]);
351     c_cvertex->n[2] = atof(av[3]);
352     (void)normalize(c_cvertex->n);
353 greg 1.8 c_cvertex->clock++;
354 greg 1.1 return(MG_OK);
355     }
356     return(MG_EUNK);
357     }
358    
359    
360     void
361     c_clearall() /* empty context tables */
362     {
363     c_uncolor = c_dfcolor;
364     c_ccolor = &c_uncolor;
365 greg 1.3 lu_done(&clr_tab);
366 greg 1.1 c_unmaterial = c_dfmaterial;
367     c_cmaterial = &c_unmaterial;
368 greg 1.3 lu_done(&mat_tab);
369 greg 1.1 c_unvertex = c_dfvertex;
370     c_cvertex = &c_unvertex;
371 greg 1.3 lu_done(&vtx_tab);
372 greg 1.1 }
373    
374    
375     C_VERTEX *
376     c_getvert(name) /* get a named vertex */
377     char *name;
378     {
379     register LUENT *lp;
380    
381     if ((lp = lu_find(&vtx_tab, name)) == NULL)
382     return(NULL);
383     return((C_VERTEX *)lp->data);
384 greg 1.5 }
385    
386    
387 greg 1.7 C_COLOR *
388     c_getcolor(name) /* get a named color */
389     char *name;
390     {
391     register LUENT *lp;
392    
393     if ((lp = lu_find(&clr_tab, name)) == NULL)
394     return(NULL);
395     return((C_COLOR *)lp->data);
396     }
397    
398    
399 greg 1.5 int
400     c_isgrey(clr) /* check if color is grey */
401     register C_COLOR *clr;
402     {
403 greg 1.8 if (!(clr->flags & (C_CSXY|C_CSSPEC)))
404 greg 1.5 return(1); /* no settings == grey */
405     c_ccvt(clr, C_CSXY);
406     return(clr->cx >= .323 && clr->cx <= .343 &&
407     clr->cy >= .323 && clr->cy <= .343);
408     }
409    
410    
411     void
412     c_ccvt(clr, fl) /* convert color representations */
413     register C_COLOR *clr;
414     int fl;
415     {
416     double x, y, z;
417     register int i;
418    
419     if (clr->flags & fl) /* already done */
420     return;
421 greg 1.8 if (!(clr->flags & (C_CSXY|C_CSSPEC))) /* nothing set! */
422 greg 1.5 *clr = c_dfcolor;
423     else if (fl & C_CSXY) { /* cspec -> cxy */
424     x = y = z = 0.;
425     for (i = 0; i < C_CNSS; i++) {
426     x += cie_xf.ssamp[i] * clr->ssamp[i];
427     y += cie_yf.ssamp[i] * clr->ssamp[i];
428     z += cie_zf.ssamp[i] * clr->ssamp[i];
429     }
430     z += x + y;
431     clr->cx = x / z;
432     clr->cy = y / z;
433     clr->flags |= C_CSXY;
434     } else { /* cxy -> cspec */
435     z = (cie_xf.ssum + cie_yf.ssum + cie_zf.ssum) / 3.;
436     x = clr->cx * z / cie_xf.ssum;
437     y = clr->cy * z / cie_yf.ssum;
438     z = (1. - clr->cx - clr->cy) * z / cie_zf.ssum;
439     clr->ssum = 0;
440     for (i = 0; i < C_CNSS; i++)
441     clr->ssum += clr->ssamp[i] =
442     x * cie_xf.ssamp[i] +
443     y * cie_yf.ssamp[i] +
444     z * cie_zf.ssamp[i] ;
445     clr->flags |= C_CSSPEC;
446     }
447     }
448    
449    
450     static int
451     setspectrum(clr, wlmin, wlmax, ac, av) /* convert a spectrum */
452     register C_COLOR *clr;
453     int wlmin, wlmax;
454     int ac;
455     char **av;
456     {
457     double scale;
458     float *va;
459     register int i;
460     int wl, pos;
461     double wl0, wlstep;
462    
463     if (wlmin < C_CMINWL || wlmin >= wlmax || wlmax > C_CMAXWL)
464     return(MG_EILL);
465     if ((va = (float *)malloc(ac*sizeof(float))) == NULL)
466     return(MG_EMEM);
467     scale = 0.; /* get values and maximum */
468     for (i = 0; i < ac; i++) {
469     if (!isflt(av[i]))
470     return(MG_ETYPE);
471     va[i] = atof(av[i]);
472     if (va[i] < 0.)
473     return(MG_EILL);
474     if (va[i] > scale)
475     scale = va[i];
476     }
477     if (scale == 0.)
478     return(MG_EILL);
479     scale = C_CMAXV / scale;
480     clr->ssum = 0; /* convert to our spacing */
481     wl0 = wlmin;
482     wlstep = (double)(wlmax - wlmin)/(ac-1);
483     pos = 0;
484     for (i = 0, wl = C_CMINWL; i < C_CNSS; i++, wl += C_CWLI)
485     if (wl < wlmin || wl > wlmax)
486     clr->ssamp[i] = 0;
487     else {
488     while (wl0 + wlstep < wl+FTINY) {
489     wl0 += wlstep;
490     pos++;
491     }
492     if (wl+FTINY >= wl0 && wl-FTINY <= wl0)
493     clr->ssamp[i] = scale*va[pos];
494     else /* interpolate if necessary */
495     clr->ssamp[i] = scale / wlstep *
496     ( va[pos]*(wl0+wlstep - wl) +
497     va[pos+1]*(wl - wl0) );
498     clr->ssum += clr->ssamp[i];
499     }
500     clr->flags = C_CDSPEC|C_CSSPEC;
501 greg 1.8 clr->clock++;
502 greg 1.5 free((MEM_PTR)va);
503     return(MG_OK);
504     }
505    
506    
507     static void
508     mixcolors(cres, w1, c1, w2, c2) /* mix two colors according to weights given */
509     register C_COLOR *cres, *c1, *c2;
510     double w1, w2;
511     {
512     double scale;
513     float cmix[C_CNSS];
514     register int i;
515    
516     if ((c1->flags|c2->flags) & C_CDSPEC) { /* spectral mixing */
517     c_ccvt(c1, C_CSSPEC);
518     c_ccvt(c2, C_CSSPEC);
519     w1 /= (double)c1->ssum;
520     w2 /= (double)c2->ssum;
521     scale = 0.;
522     for (i = 0; i < C_CNSS; i++) {
523     cmix[i] = w1*c1->ssamp[i] + w2*c2->ssamp[i];
524     if (cmix[i] > scale)
525     scale = cmix[i];
526     }
527     scale = C_CMAXV / scale;
528     cres->ssum = 0;
529     for (i = 0; i < C_CNSS; i++)
530     cres->ssum += cres->ssamp[i] = scale*cmix[i] + .5;
531     cres->flags = C_CDSPEC|C_CSSPEC;
532     } else { /* CIE xy mixing */
533     c_ccvt(c1, C_CSXY);
534     c_ccvt(c2, C_CSXY);
535     scale = 1. / (w1/c1->cy + w2/c2->cy);
536     cres->cx = (c1->cx*w1/c1->cy + c2->cx*w2/c2->cy) * scale;
537     cres->cy = (w1 + w2) * scale;
538     cres->flags = C_CDXY|C_CSXY;
539     }
540 greg 1.1 }