ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/context.c
Revision: 1.8
Committed: Sat Jun 25 11:55:45 1994 UTC (29 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.7: +14 -2 lines
Log Message:
added name and clock members to C_COLOR and C_VERTEX structures

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