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

# Content
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 #include <math.h>
13 #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 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
36 /* 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
41 static int setspectrum();
42 static void mixcolors();
43
44
45 int
46 c_hcolor(ac, av) /* handle color entity */
47 int ac;
48 register char **av;
49 {
50 double w, wsum;
51 register int i;
52 register LUENT *lp;
53
54 switch (mg_entity(av[0])) {
55 case MG_E_COLOR: /* get/set color context */
56 if (ac > 4)
57 return(MG_EARGC);
58 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 c_ccolor->name = lp->key;
87 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 c_ccolor->name = lp->key;
96 c_ccolor->clock = 1;
97 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 c_ccolor->flags = C_CDXY|C_CSXY;
108 if (c_ccolor->cx < 0. | c_ccolor->cy < 0. |
109 c_ccolor->cx + c_ccolor->cy > 1.)
110 return(MG_EILL);
111 c_ccolor->clock++;
112 return(MG_OK);
113 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 }
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 if (ac > 4)
163 return(MG_EARGC);
164 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 c_cmaterial->name = lp->key;
193 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 c_cmaterial->name = lp->key;
202 c_cmaterial->clock = 1;
203 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 c_cmaterial->clock++;
216 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 c_cmaterial->clock++;
227 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 c_cmaterial->clock++;
238 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 c_cmaterial->clock++;
251 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 c_cmaterial->clock++;
264 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 if (ac > 4)
280 return(MG_EARGC);
281 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 c_cvertex->name = lp->key
310 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 c_cvertex->name = lp->key
319 c_cvertex->clock = 1;
320 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 c_cvertex->clock++;
332 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 c_cvertex->clock++;
343 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 lu_done(&clr_tab);
355 c_unmaterial = c_dfmaterial;
356 c_cmaterial = &c_unmaterial;
357 lu_done(&mat_tab);
358 c_unvertex = c_dfvertex;
359 c_cvertex = &c_unvertex;
360 lu_done(&vtx_tab);
361 }
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 }
374
375
376 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 int
389 c_isgrey(clr) /* check if color is grey */
390 register C_COLOR *clr;
391 {
392 if (!(clr->flags & (C_CSXY|C_CSSPEC)))
393 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 if (!(clr->flags & (C_CSXY|C_CSSPEC))) /* nothing set! */
411 *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 clr->clock++;
491 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 cres->clock++; /* record the change */
530 }