ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/context.c
Revision: 1.30
Committed: Thu Feb 3 19:36:10 2011 UTC (14 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.29: +6 -83 lines
Log Message:
Moved some routines into ccolor.c

File Contents

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