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 (13 years, 4 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: context.c,v 1.29 2011/01/03 20:30:21 greg Exp $";
3 #endif
4 /*
5 * Context handlers
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #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 char *c_ccname = NULL;
26 C_MATERIAL *c_cmaterial = &c_unmaterial;
27 char *c_cmname = NULL;
28 C_VERTEX *c_cvertex = &c_unvertex;
29 char *c_cvname = NULL;
30
31 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
35 static int setspectrum();
36
37
38 int
39 c_hcolor(ac, av) /* handle color entity */
40 int ac;
41 register char **av;
42 {
43 double w, wsum;
44 register int i;
45 register LUENT *lp;
46
47 switch (mg_entity(av[0])) {
48 case MG_E_COLOR: /* get/set color context */
49 if (ac > 4)
50 return(MG_EARGC);
51 if (ac == 1) { /* set unnamed color context */
52 c_uncolor = c_dfcolor;
53 c_ccolor = &c_uncolor;
54 c_ccname = NULL;
55 return(MG_OK);
56 }
57 if (!isname(av[1]))
58 return(MG_EILL);
59 lp = lu_find(&clr_tab, av[1]); /* lookup context */
60 if (lp == NULL)
61 return(MG_EMEM);
62 c_ccname = lp->key;
63 c_ccolor = (C_COLOR *)lp->data;
64 if (ac == 2) { /* reestablish previous context */
65 if (c_ccolor == NULL)
66 return(MG_EUNDEF);
67 return(MG_OK);
68 }
69 if (av[2][0] != '=' || av[2][1])
70 return(MG_ETYPE);
71 if (c_ccolor == NULL) { /* create new color context */
72 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 c_ccname = lp->key;
80 c_ccolor = (C_COLOR *)lp->data;
81 c_ccolor->clock = 0;
82 c_ccolor->client_data = NULL;
83 }
84 i = c_ccolor->clock;
85 if (ac == 3) { /* use default template */
86 *c_ccolor = c_dfcolor;
87 c_ccolor->clock = i + 1;
88 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 c_ccolor->clock = i + 1;
97 return(MG_OK);
98 case MG_E_CXY: /* assign CIE XY value */
99 if (ac != 3)
100 return(MG_EARGC);
101 if (!isflt(av[1]) | !isflt(av[2]))
102 return(MG_ETYPE);
103 c_ccolor->cx = atof(av[1]);
104 c_ccolor->cy = atof(av[2]);
105 c_ccolor->flags = C_CDXY|C_CSXY;
106 if ((c_ccolor->cx < 0.) | (c_ccolor->cy < 0.) |
107 (c_ccolor->cx + c_ccolor->cy > 1.))
108 return(MG_EILL);
109 c_ccolor->clock++;
110 return(MG_OK);
111 case MG_E_CSPEC: /* assign spectral values */
112 if (ac < 5)
113 return(MG_EARGC);
114 if (!isflt(av[1]) | !isflt(av[2]))
115 return(MG_ETYPE);
116 return(setspectrum(c_ccolor, atof(av[1]), atof(av[2]),
117 ac-3, av+3));
118 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 if (!c_bbtemp(c_ccolor, atof(av[1])))
124 return(MG_EILL);
125 c_ccolor->clock++;
126 return(MG_OK);
127 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 c_cmix(c_ccolor, wsum, c_ccolor,
147 w, (C_COLOR *)lp->data);
148 wsum += w;
149 }
150 if (wsum <= 0.)
151 return(MG_EILL);
152 c_ccolor->clock++;
153 return(MG_OK);
154 }
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 int i;
165 register LUENT *lp;
166
167 switch (mg_entity(av[0])) {
168 case MG_E_MATERIAL: /* get/set material context */
169 if (ac > 4)
170 return(MG_EARGC);
171 if (ac == 1) { /* set unnamed material context */
172 c_unmaterial = c_dfmaterial;
173 c_cmaterial = &c_unmaterial;
174 c_cmname = NULL;
175 return(MG_OK);
176 }
177 if (!isname(av[1]))
178 return(MG_EILL);
179 lp = lu_find(&mat_tab, av[1]); /* lookup context */
180 if (lp == NULL)
181 return(MG_EMEM);
182 c_cmname = lp->key;
183 c_cmaterial = (C_MATERIAL *)lp->data;
184 if (ac == 2) { /* reestablish previous context */
185 if (c_cmaterial == NULL)
186 return(MG_EUNDEF);
187 return(MG_OK);
188 }
189 if (av[2][0] != '=' || av[2][1])
190 return(MG_ETYPE);
191 if (c_cmaterial == NULL) { /* create new material */
192 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 c_cmname = lp->key;
200 c_cmaterial = (C_MATERIAL *)lp->data;
201 c_cmaterial->clock = 0;
202 c_cmaterial->client_data = NULL;
203 }
204 i = c_cmaterial->clock;
205 if (ac == 3) { /* use default template */
206 *c_cmaterial = c_dfmaterial;
207 c_cmaterial->clock = i + 1;
208 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 c_cmaterial->clock = i + 1;
217 return(MG_OK);
218 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 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 if ((c_cmaterial->rd < 0.) | (c_cmaterial->rd > 1.))
236 return(MG_EILL);
237 c_cmaterial->rd_c = *c_ccolor;
238 c_cmaterial->clock++;
239 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 c_cmaterial->clock++;
250 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 if ((c_cmaterial->td < 0.) | (c_cmaterial->td > 1.))
258 return(MG_EILL);
259 c_cmaterial->td_c = *c_ccolor;
260 c_cmaterial->clock++;
261 return(MG_OK);
262 case MG_E_RS: /* set specular reflectance */
263 if (ac != 3)
264 return(MG_EARGC);
265 if (!isflt(av[1]) | !isflt(av[2]))
266 return(MG_ETYPE);
267 c_cmaterial->rs = atof(av[1]);
268 c_cmaterial->rs_a = atof(av[2]);
269 if ((c_cmaterial->rs < 0.) | (c_cmaterial->rs > 1.) |
270 (c_cmaterial->rs_a < 0.))
271 return(MG_EILL);
272 c_cmaterial->rs_c = *c_ccolor;
273 c_cmaterial->clock++;
274 return(MG_OK);
275 case MG_E_TS: /* set specular transmittance */
276 if (ac != 3)
277 return(MG_EARGC);
278 if (!isflt(av[1]) | !isflt(av[2]))
279 return(MG_ETYPE);
280 c_cmaterial->ts = atof(av[1]);
281 c_cmaterial->ts_a = atof(av[2]);
282 if ((c_cmaterial->ts < 0.) | (c_cmaterial->ts > 1.) |
283 (c_cmaterial->ts_a < 0.))
284 return(MG_EILL);
285 c_cmaterial->ts_c = *c_ccolor;
286 c_cmaterial->clock++;
287 return(MG_OK);
288 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 }
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 int i;
313 register LUENT *lp;
314
315 switch (mg_entity(av[0])) {
316 case MG_E_VERTEX: /* get/set vertex context */
317 if (ac > 4)
318 return(MG_EARGC);
319 if (ac == 1) { /* set unnamed vertex context */
320 c_unvertex = c_dfvertex;
321 c_cvertex = &c_unvertex;
322 c_cvname = NULL;
323 return(MG_OK);
324 }
325 if (!isname(av[1]))
326 return(MG_EILL);
327 lp = lu_find(&vtx_tab, av[1]); /* lookup context */
328 if (lp == NULL)
329 return(MG_EMEM);
330 c_cvname = lp->key;
331 c_cvertex = (C_VERTEX *)lp->data;
332 if (ac == 2) { /* reestablish previous context */
333 if (c_cvertex == NULL)
334 return(MG_EUNDEF);
335 return(MG_OK);
336 }
337 if (av[2][0] != '=' || av[2][1])
338 return(MG_ETYPE);
339 if (c_cvertex == NULL) { /* create new vertex context */
340 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 c_cvname = lp->key;
348 c_cvertex = (C_VERTEX *)lp->data;
349 c_cvertex->clock = 0;
350 c_cvertex->client_data = NULL;
351 }
352 i = c_cvertex->clock;
353 if (ac == 3) { /* use default template */
354 *c_cvertex = c_dfvertex;
355 c_cvertex->clock = i + 1;
356 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 c_cvertex->clock = i + 1;
365 return(MG_OK);
366 case MG_E_POINT: /* set point */
367 if (ac != 4)
368 return(MG_EARGC);
369 if (!isflt(av[1]) | !isflt(av[2]) | !isflt(av[3]))
370 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 c_cvertex->clock++;
375 return(MG_OK);
376 case MG_E_NORMAL: /* set normal */
377 if (ac != 4)
378 return(MG_EARGC);
379 if (!isflt(av[1]) | !isflt(av[2]) | !isflt(av[3]))
380 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 c_cvertex->clock++;
386 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 c_ccname = NULL;
398 lu_done(&clr_tab);
399 c_unmaterial = c_dfmaterial;
400 c_cmaterial = &c_unmaterial;
401 c_cmname = NULL;
402 lu_done(&mat_tab);
403 c_unvertex = c_dfvertex;
404 c_cvertex = &c_unvertex;
405 c_cvname = NULL;
406 lu_done(&vtx_tab);
407 }
408
409
410 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 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 }
432
433
434 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 static int
447 setspectrum(clr, wlmin, wlmax, ac, av) /* convert a spectrum */
448 register C_COLOR *clr;
449 double wlmin, wlmax;
450 int ac;
451 char **av;
452 {
453 double scale;
454 float va[C_CNSS];
455 register int i, pos;
456 int n, imax;
457 int wl;
458 double wl0, wlstep;
459 double boxpos, boxstep;
460 /* check bounds */
461 if ((wlmax <= C_CMINWL) | (wlmax <= wlmin) | (wlmin >= C_CMAXWL))
462 return(MG_EILL);
463 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 boxpos = 0;
474 boxstep = 1;
475 if (wlstep < C_CWLI) {
476 imax = (wlmax - wlmin)/C_CWLI + (1-FTINY);
477 boxpos = (wlmin - C_CMINWL)/C_CWLI;
478 boxstep = wlstep/C_CWLI;
479 wlstep = C_CWLI;
480 }
481 scale = 0.; /* get values and maximum */
482 pos = 0;
483 for (i = 0; i < imax; i++) {
484 va[i] = 0.; n = 0;
485 while (boxpos < i+.5 && pos < ac) {
486 if (!isflt(av[pos]))
487 return(MG_ETYPE);
488 va[i] += atof(av[pos++]);
489 n++;
490 boxpos += boxstep;
491 }
492 if (n > 1)
493 va[i] /= (double)n;
494 if (va[i] > scale)
495 scale = va[i];
496 else if (va[i] < -scale)
497 scale = -va[i];
498 }
499 if (scale <= FTINY)
500 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 if ((wl < wlmin) | (wl > wlmax))
507 clr->ssamp[i] = 0;
508 else {
509 while (wl0 + wlstep < wl+FTINY) {
510 wl0 += wlstep;
511 pos++;
512 }
513 if ((wl+FTINY >= wl0) & (wl-FTINY <= wl0))
514 clr->ssamp[i] = scale*va[pos] + .5;
515 else /* interpolate if necessary */
516 clr->ssamp[i] = .5 + scale / wlstep *
517 ( 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 clr->clock++;
523 return(MG_OK);
524 }