| 1 | greg | 1.24 | /* Copyright (c) 1997 Regents of the University of California */ | 
| 2 | greg | 1.1 |  | 
| 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 | greg | 1.12 | char            *c_ccname = NULL; | 
| 30 | greg | 1.1 | C_MATERIAL      *c_cmaterial = &c_unmaterial; | 
| 31 | greg | 1.12 | char            *c_cmname = NULL; | 
| 32 | greg | 1.1 | C_VERTEX        *c_cvertex = &c_unvertex; | 
| 33 | greg | 1.12 | char            *c_cvname = NULL; | 
| 34 | greg | 1.1 |  | 
| 35 | greg | 1.3 | static LUTAB    clr_tab = LU_SINIT(free,free);  /* color lookup table */ | 
| 36 |  |  | static LUTAB    mat_tab = LU_SINIT(free,free);  /* material lookup table */ | 
| 37 |  |  | static LUTAB    vtx_tab = LU_SINIT(free,free);  /* vertex lookup table */ | 
| 38 | greg | 1.1 |  | 
| 39 | greg | 1.19 | /* CIE 1931 Standard Observer curves */ | 
| 40 |  |  | static C_COLOR  cie_xf = { 1, C_CDSPEC|C_CSSPEC|C_CSXY|C_CSEFF, | 
| 41 |  |  | {14,42,143,435,1344,2839,3483,3362,2908,1954,956, | 
| 42 |  |  | 320,49,93,633,1655,2904,4334,5945,7621,9163,10263, | 
| 43 |  |  | 10622,10026,8544,6424,4479,2835,1649,874,468,227, | 
| 44 |  |  | 114,58,29,14,7,3,2,1,0}, 106836L, .467, .368, 362.230 | 
| 45 |  |  | }; | 
| 46 |  |  | static C_COLOR  cie_yf = { 1, C_CDSPEC|C_CSSPEC|C_CSXY|C_CSEFF, | 
| 47 |  |  | {0,1,4,12,40,116,230,380,600,910,1390,2080,3230, | 
| 48 |  |  | 5030,7100,8620,9540,9950,9950,9520,8700,7570,6310, | 
| 49 |  |  | 5030,3810,2650,1750,1070,610,320,170,82,41,21,10, | 
| 50 |  |  | 5,2,1,1,0,0}, 106856L, .398, .542, 493.525 | 
| 51 |  |  | }; | 
| 52 |  |  | static C_COLOR  cie_zf = { 1, C_CDSPEC|C_CSSPEC|C_CSXY|C_CSEFF, | 
| 53 |  |  | {65,201,679,2074,6456,13856,17471,17721,16692, | 
| 54 |  |  | 12876,8130,4652,2720,1582,782,422,203,87,39,21,17, | 
| 55 |  |  | 11,8,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, | 
| 56 |  |  | 106770L, .147, .077, 54.363 | 
| 57 |  |  | }; | 
| 58 |  |  | /* Derived CIE 1931 Primaries (imaginary) */ | 
| 59 |  |  | static C_COLOR  cie_xp = { 1, C_CDSPEC|C_CSSPEC|C_CSXY, | 
| 60 |  |  | {-174,-198,-195,-197,-202,-213,-235,-272,-333, | 
| 61 |  |  | -444,-688,-1232,-2393,-4497,-6876,-6758,-5256, | 
| 62 |  |  | -3100,-815,1320,3200,4782,5998,6861,7408,7754, | 
| 63 |  |  | 7980,8120,8199,8240,8271,8292,8309,8283,8469, | 
| 64 |  |  | 8336,8336,8336,8336,8336,8336}, | 
| 65 |  |  | 127424L, 1., .0, | 
| 66 |  |  | }; | 
| 67 |  |  | static C_COLOR  cie_yp = { 1, C_CDSPEC|C_CSSPEC|C_CSXY, | 
| 68 |  |  | {-451,-431,-431,-430,-427,-417,-399,-366,-312, | 
| 69 |  |  | -204,57,691,2142,4990,8810,9871,9122,7321,5145, | 
| 70 |  |  | 3023,1123,-473,-1704,-2572,-3127,-3474,-3704, | 
| 71 |  |  | -3846,-3927,-3968,-3999,-4021,-4038,-4012,-4201, | 
| 72 |  |  | -4066,-4066,-4066,-4066,-4066,-4066}, | 
| 73 |  |  | -23035L, .0, 1., | 
| 74 |  |  | }; | 
| 75 |  |  | static C_COLOR  cie_zp = { 1, C_CDSPEC|C_CSSPEC|C_CSXY, | 
| 76 |  |  | {4051,4054,4052,4053,4054,4056,4059,4064,4071, | 
| 77 |  |  | 4074,4056,3967,3677,2933,1492,313,-440,-795, | 
| 78 |  |  | -904,-918,-898,-884,-869,-863,-855,-855,-851, | 
| 79 |  |  | -848,-847,-846,-846,-846,-845,-846,-843,-845, | 
| 80 |  |  | -845,-845,-845,-845,-845}, | 
| 81 |  |  | 36057L, .0, .0, | 
| 82 |  |  | }; | 
| 83 | greg | 1.1 |  | 
| 84 | greg | 1.5 | static int      setspectrum(); | 
| 85 | greg | 1.18 | static int      setbbtemp(); | 
| 86 | greg | 1.5 | static void     mixcolors(); | 
| 87 |  |  |  | 
| 88 |  |  |  | 
| 89 | greg | 1.1 | int | 
| 90 |  |  | c_hcolor(ac, av)                /* handle color entity */ | 
| 91 |  |  | int     ac; | 
| 92 |  |  | register char   **av; | 
| 93 |  |  | { | 
| 94 | greg | 1.5 | double  w, wsum; | 
| 95 |  |  | register int    i; | 
| 96 | greg | 1.1 | register LUENT  *lp; | 
| 97 |  |  |  | 
| 98 |  |  | switch (mg_entity(av[0])) { | 
| 99 |  |  | case MG_E_COLOR:        /* get/set color context */ | 
| 100 | greg | 1.4 | if (ac > 4) | 
| 101 |  |  | return(MG_EARGC); | 
| 102 | greg | 1.1 | if (ac == 1) {          /* set unnamed color context */ | 
| 103 |  |  | c_uncolor = c_dfcolor; | 
| 104 |  |  | c_ccolor = &c_uncolor; | 
| 105 | greg | 1.12 | c_ccname = NULL; | 
| 106 | greg | 1.1 | return(MG_OK); | 
| 107 |  |  | } | 
| 108 | greg | 1.22 | if (!isname(av[1])) | 
| 109 |  |  | return(MG_EILL); | 
| 110 | greg | 1.1 | lp = lu_find(&clr_tab, av[1]);  /* lookup context */ | 
| 111 |  |  | if (lp == NULL) | 
| 112 |  |  | return(MG_EMEM); | 
| 113 | greg | 1.14 | c_ccname = lp->key; | 
| 114 | greg | 1.9 | c_ccolor = (C_COLOR *)lp->data; | 
| 115 | greg | 1.1 | if (ac == 2) {          /* reestablish previous context */ | 
| 116 | greg | 1.9 | if (c_ccolor == NULL) | 
| 117 | greg | 1.1 | return(MG_EUNDEF); | 
| 118 |  |  | return(MG_OK); | 
| 119 |  |  | } | 
| 120 |  |  | if (av[2][0] != '=' || av[2][1]) | 
| 121 |  |  | return(MG_ETYPE); | 
| 122 | greg | 1.9 | if (c_ccolor == NULL) { /* create new color context */ | 
| 123 | greg | 1.1 | lp->key = (char *)malloc(strlen(av[1])+1); | 
| 124 |  |  | if (lp->key == NULL) | 
| 125 |  |  | return(MG_EMEM); | 
| 126 |  |  | strcpy(lp->key, av[1]); | 
| 127 |  |  | lp->data = (char *)malloc(sizeof(C_COLOR)); | 
| 128 |  |  | if (lp->data == NULL) | 
| 129 |  |  | return(MG_EMEM); | 
| 130 | greg | 1.14 | c_ccname = lp->key; | 
| 131 | greg | 1.9 | c_ccolor = (C_COLOR *)lp->data; | 
| 132 |  |  | c_ccolor->clock = 0; | 
| 133 | greg | 1.1 | } | 
| 134 | greg | 1.10 | i = c_ccolor->clock; | 
| 135 | greg | 1.1 | if (ac == 3) {          /* use default template */ | 
| 136 |  |  | *c_ccolor = c_dfcolor; | 
| 137 | greg | 1.9 | c_ccolor->clock = i + 1; | 
| 138 | greg | 1.1 | return(MG_OK); | 
| 139 |  |  | } | 
| 140 |  |  | lp = lu_find(&clr_tab, av[3]);  /* lookup template */ | 
| 141 |  |  | if (lp == NULL) | 
| 142 |  |  | return(MG_EMEM); | 
| 143 |  |  | if (lp->data == NULL) | 
| 144 |  |  | return(MG_EUNDEF); | 
| 145 |  |  | *c_ccolor = *(C_COLOR *)lp->data; | 
| 146 | greg | 1.9 | c_ccolor->clock = i + 1; | 
| 147 | greg | 1.1 | return(MG_OK); | 
| 148 |  |  | case MG_E_CXY:          /* assign CIE XY value */ | 
| 149 |  |  | if (ac != 3) | 
| 150 |  |  | return(MG_EARGC); | 
| 151 | greg | 1.18 | if (!isflt(av[1]) | !isflt(av[2])) | 
| 152 | greg | 1.1 | return(MG_ETYPE); | 
| 153 |  |  | c_ccolor->cx = atof(av[1]); | 
| 154 |  |  | c_ccolor->cy = atof(av[2]); | 
| 155 | greg | 1.5 | c_ccolor->flags = C_CDXY|C_CSXY; | 
| 156 | greg | 1.1 | if (c_ccolor->cx < 0. | c_ccolor->cy < 0. | | 
| 157 |  |  | c_ccolor->cx + c_ccolor->cy > 1.) | 
| 158 |  |  | return(MG_EILL); | 
| 159 | greg | 1.8 | c_ccolor->clock++; | 
| 160 | greg | 1.1 | return(MG_OK); | 
| 161 | greg | 1.5 | case MG_E_CSPEC:        /* assign spectral values */ | 
| 162 |  |  | if (ac < 5) | 
| 163 |  |  | return(MG_EARGC); | 
| 164 | greg | 1.18 | if (!isflt(av[1]) | !isflt(av[2])) | 
| 165 | greg | 1.5 | return(MG_ETYPE); | 
| 166 | greg | 1.17 | return(setspectrum(c_ccolor, atof(av[1]), atof(av[2]), | 
| 167 | greg | 1.5 | ac-3, av+3)); | 
| 168 | greg | 1.18 | case MG_E_CCT:          /* assign black body spectrum */ | 
| 169 |  |  | if (ac != 2) | 
| 170 |  |  | return(MG_EARGC); | 
| 171 |  |  | if (!isflt(av[1])) | 
| 172 |  |  | return(MG_ETYPE); | 
| 173 |  |  | return(setbbtemp(c_ccolor, atof(av[1]))); | 
| 174 | greg | 1.5 | case MG_E_CMIX:         /* mix colors */ | 
| 175 |  |  | if (ac < 5 || (ac-1)%2) | 
| 176 |  |  | return(MG_EARGC); | 
| 177 |  |  | if (!isflt(av[1])) | 
| 178 |  |  | return(MG_ETYPE); | 
| 179 |  |  | wsum = atof(av[1]); | 
| 180 |  |  | if ((lp = lu_find(&clr_tab, av[2])) == NULL) | 
| 181 |  |  | return(MG_EMEM); | 
| 182 |  |  | if (lp->data == NULL) | 
| 183 |  |  | return(MG_EUNDEF); | 
| 184 |  |  | *c_ccolor = *(C_COLOR *)lp->data; | 
| 185 |  |  | for (i = 3; i < ac; i += 2) { | 
| 186 |  |  | if (!isflt(av[i])) | 
| 187 |  |  | return(MG_ETYPE); | 
| 188 |  |  | w = atof(av[i]); | 
| 189 |  |  | if ((lp = lu_find(&clr_tab, av[i+1])) == NULL) | 
| 190 |  |  | return(MG_EMEM); | 
| 191 |  |  | if (lp->data == NULL) | 
| 192 |  |  | return(MG_EUNDEF); | 
| 193 |  |  | mixcolors(c_ccolor, wsum, c_ccolor, | 
| 194 |  |  | w, (C_COLOR *)lp->data); | 
| 195 |  |  | wsum += w; | 
| 196 |  |  | } | 
| 197 | greg | 1.24 | if (wsum <= 0.) | 
| 198 |  |  | return(MG_EILL); | 
| 199 | greg | 1.10 | c_ccolor->clock++; | 
| 200 | greg | 1.5 | return(MG_OK); | 
| 201 | greg | 1.1 | } | 
| 202 |  |  | return(MG_EUNK); | 
| 203 |  |  | } | 
| 204 |  |  |  | 
| 205 |  |  |  | 
| 206 |  |  | int | 
| 207 |  |  | c_hmaterial(ac, av)             /* handle material entity */ | 
| 208 |  |  | int     ac; | 
| 209 |  |  | register char   **av; | 
| 210 |  |  | { | 
| 211 | greg | 1.9 | int     i; | 
| 212 | greg | 1.1 | register LUENT  *lp; | 
| 213 |  |  |  | 
| 214 |  |  | switch (mg_entity(av[0])) { | 
| 215 |  |  | case MG_E_MATERIAL:     /* get/set material context */ | 
| 216 | greg | 1.4 | if (ac > 4) | 
| 217 |  |  | return(MG_EARGC); | 
| 218 | greg | 1.1 | if (ac == 1) {          /* set unnamed material context */ | 
| 219 |  |  | c_unmaterial = c_dfmaterial; | 
| 220 |  |  | c_cmaterial = &c_unmaterial; | 
| 221 | greg | 1.12 | c_cmname = NULL; | 
| 222 | greg | 1.1 | return(MG_OK); | 
| 223 |  |  | } | 
| 224 | greg | 1.22 | if (!isname(av[1])) | 
| 225 |  |  | return(MG_EILL); | 
| 226 | greg | 1.1 | lp = lu_find(&mat_tab, av[1]);  /* lookup context */ | 
| 227 |  |  | if (lp == NULL) | 
| 228 |  |  | return(MG_EMEM); | 
| 229 | greg | 1.14 | c_cmname = lp->key; | 
| 230 | greg | 1.9 | c_cmaterial = (C_MATERIAL *)lp->data; | 
| 231 | greg | 1.1 | if (ac == 2) {          /* reestablish previous context */ | 
| 232 | greg | 1.9 | if (c_cmaterial == NULL) | 
| 233 | greg | 1.1 | return(MG_EUNDEF); | 
| 234 |  |  | return(MG_OK); | 
| 235 |  |  | } | 
| 236 |  |  | if (av[2][0] != '=' || av[2][1]) | 
| 237 |  |  | return(MG_ETYPE); | 
| 238 | greg | 1.9 | if (c_cmaterial == NULL) {      /* create new material */ | 
| 239 | greg | 1.1 | lp->key = (char *)malloc(strlen(av[1])+1); | 
| 240 |  |  | if (lp->key == NULL) | 
| 241 |  |  | return(MG_EMEM); | 
| 242 |  |  | strcpy(lp->key, av[1]); | 
| 243 |  |  | lp->data = (char *)malloc(sizeof(C_MATERIAL)); | 
| 244 |  |  | if (lp->data == NULL) | 
| 245 |  |  | return(MG_EMEM); | 
| 246 | greg | 1.14 | c_cmname = lp->key; | 
| 247 | greg | 1.9 | c_cmaterial = (C_MATERIAL *)lp->data; | 
| 248 |  |  | c_cmaterial->clock = 0; | 
| 249 | greg | 1.1 | } | 
| 250 | greg | 1.10 | i = c_cmaterial->clock; | 
| 251 | greg | 1.1 | if (ac == 3) {          /* use default template */ | 
| 252 |  |  | *c_cmaterial = c_dfmaterial; | 
| 253 | greg | 1.9 | c_cmaterial->clock = i + 1; | 
| 254 | greg | 1.1 | return(MG_OK); | 
| 255 |  |  | } | 
| 256 |  |  | lp = lu_find(&mat_tab, av[3]);  /* lookup template */ | 
| 257 |  |  | if (lp == NULL) | 
| 258 |  |  | return(MG_EMEM); | 
| 259 |  |  | if (lp->data == NULL) | 
| 260 |  |  | return(MG_EUNDEF); | 
| 261 |  |  | *c_cmaterial = *(C_MATERIAL *)lp->data; | 
| 262 | greg | 1.9 | c_cmaterial->clock = i + 1; | 
| 263 | greg | 1.1 | return(MG_OK); | 
| 264 | greg | 1.21 | case MG_E_IR:           /* set index of refraction */ | 
| 265 |  |  | if (ac != 3) | 
| 266 |  |  | return(MG_EARGC); | 
| 267 |  |  | if (!isflt(av[1]) | !isflt(av[2])) | 
| 268 |  |  | return(MG_ETYPE); | 
| 269 |  |  | c_cmaterial->nr = atof(av[1]); | 
| 270 |  |  | c_cmaterial->ni = atof(av[2]); | 
| 271 |  |  | if (c_cmaterial->nr <= FTINY) | 
| 272 |  |  | return(MG_EILL); | 
| 273 |  |  | c_cmaterial->clock++; | 
| 274 |  |  | return(MG_OK); | 
| 275 | greg | 1.1 | case MG_E_RD:           /* set diffuse reflectance */ | 
| 276 |  |  | if (ac != 2) | 
| 277 |  |  | return(MG_EARGC); | 
| 278 |  |  | if (!isflt(av[1])) | 
| 279 |  |  | return(MG_ETYPE); | 
| 280 |  |  | c_cmaterial->rd = atof(av[1]); | 
| 281 |  |  | if (c_cmaterial->rd < 0. | c_cmaterial->rd > 1.) | 
| 282 |  |  | return(MG_EILL); | 
| 283 |  |  | c_cmaterial->rd_c = *c_ccolor; | 
| 284 | greg | 1.2 | c_cmaterial->clock++; | 
| 285 | greg | 1.1 | return(MG_OK); | 
| 286 |  |  | case MG_E_ED:           /* set diffuse emittance */ | 
| 287 |  |  | if (ac != 2) | 
| 288 |  |  | return(MG_EARGC); | 
| 289 |  |  | if (!isflt(av[1])) | 
| 290 |  |  | return(MG_ETYPE); | 
| 291 |  |  | c_cmaterial->ed = atof(av[1]); | 
| 292 |  |  | if (c_cmaterial->ed < 0.) | 
| 293 |  |  | return(MG_EILL); | 
| 294 |  |  | c_cmaterial->ed_c = *c_ccolor; | 
| 295 | greg | 1.2 | c_cmaterial->clock++; | 
| 296 | greg | 1.1 | return(MG_OK); | 
| 297 |  |  | case MG_E_TD:           /* set diffuse transmittance */ | 
| 298 |  |  | if (ac != 2) | 
| 299 |  |  | return(MG_EARGC); | 
| 300 |  |  | if (!isflt(av[1])) | 
| 301 |  |  | return(MG_ETYPE); | 
| 302 |  |  | c_cmaterial->td = atof(av[1]); | 
| 303 |  |  | if (c_cmaterial->td < 0. | c_cmaterial->td > 1.) | 
| 304 |  |  | return(MG_EILL); | 
| 305 |  |  | c_cmaterial->td_c = *c_ccolor; | 
| 306 | greg | 1.8 | c_cmaterial->clock++; | 
| 307 | greg | 1.1 | return(MG_OK); | 
| 308 |  |  | case MG_E_RS:           /* set specular reflectance */ | 
| 309 |  |  | if (ac != 3) | 
| 310 |  |  | return(MG_EARGC); | 
| 311 | greg | 1.18 | if (!isflt(av[1]) | !isflt(av[2])) | 
| 312 | greg | 1.1 | return(MG_ETYPE); | 
| 313 |  |  | c_cmaterial->rs = atof(av[1]); | 
| 314 |  |  | c_cmaterial->rs_a = atof(av[2]); | 
| 315 |  |  | if (c_cmaterial->rs < 0. | c_cmaterial->rs > 1. | | 
| 316 |  |  | c_cmaterial->rs_a < 0.) | 
| 317 |  |  | return(MG_EILL); | 
| 318 |  |  | c_cmaterial->rs_c = *c_ccolor; | 
| 319 | greg | 1.2 | c_cmaterial->clock++; | 
| 320 | greg | 1.1 | return(MG_OK); | 
| 321 |  |  | case MG_E_TS:           /* set specular transmittance */ | 
| 322 |  |  | if (ac != 3) | 
| 323 |  |  | return(MG_EARGC); | 
| 324 | greg | 1.18 | if (!isflt(av[1]) | !isflt(av[2])) | 
| 325 | greg | 1.1 | return(MG_ETYPE); | 
| 326 |  |  | c_cmaterial->ts = atof(av[1]); | 
| 327 |  |  | c_cmaterial->ts_a = atof(av[2]); | 
| 328 |  |  | if (c_cmaterial->ts < 0. | c_cmaterial->ts > 1. | | 
| 329 |  |  | c_cmaterial->ts_a < 0.) | 
| 330 |  |  | return(MG_EILL); | 
| 331 |  |  | c_cmaterial->ts_c = *c_ccolor; | 
| 332 | greg | 1.2 | c_cmaterial->clock++; | 
| 333 | greg | 1.1 | return(MG_OK); | 
| 334 | greg | 1.13 | case MG_E_SIDES:        /* set number of sides */ | 
| 335 |  |  | if (ac != 2) | 
| 336 |  |  | return(MG_EARGC); | 
| 337 |  |  | if (!isint(av[1])) | 
| 338 |  |  | return(MG_ETYPE); | 
| 339 |  |  | i = atoi(av[1]); | 
| 340 |  |  | if (i == 1) | 
| 341 |  |  | c_cmaterial->sided = 1; | 
| 342 |  |  | else if (i == 2) | 
| 343 |  |  | c_cmaterial->sided = 0; | 
| 344 |  |  | else | 
| 345 |  |  | return(MG_EILL); | 
| 346 |  |  | c_cmaterial->clock++; | 
| 347 |  |  | return(MG_OK); | 
| 348 | greg | 1.1 | } | 
| 349 |  |  | return(MG_EUNK); | 
| 350 |  |  | } | 
| 351 |  |  |  | 
| 352 |  |  |  | 
| 353 |  |  | int | 
| 354 |  |  | c_hvertex(ac, av)               /* handle a vertex entity */ | 
| 355 |  |  | int     ac; | 
| 356 |  |  | register char   **av; | 
| 357 |  |  | { | 
| 358 | greg | 1.9 | int     i; | 
| 359 | greg | 1.1 | register LUENT  *lp; | 
| 360 |  |  |  | 
| 361 |  |  | switch (mg_entity(av[0])) { | 
| 362 |  |  | case MG_E_VERTEX:       /* get/set vertex context */ | 
| 363 | greg | 1.4 | if (ac > 4) | 
| 364 |  |  | return(MG_EARGC); | 
| 365 | greg | 1.1 | if (ac == 1) {          /* set unnamed vertex context */ | 
| 366 |  |  | c_unvertex = c_dfvertex; | 
| 367 |  |  | c_cvertex = &c_unvertex; | 
| 368 | greg | 1.12 | c_cvname = NULL; | 
| 369 | greg | 1.1 | return(MG_OK); | 
| 370 |  |  | } | 
| 371 | greg | 1.22 | if (!isname(av[1])) | 
| 372 |  |  | return(MG_EILL); | 
| 373 | greg | 1.1 | lp = lu_find(&vtx_tab, av[1]);  /* lookup context */ | 
| 374 |  |  | if (lp == NULL) | 
| 375 |  |  | return(MG_EMEM); | 
| 376 | greg | 1.14 | c_cvname = lp->key; | 
| 377 | greg | 1.9 | c_cvertex = (C_VERTEX *)lp->data; | 
| 378 | greg | 1.1 | if (ac == 2) {          /* reestablish previous context */ | 
| 379 | greg | 1.9 | if (c_cvertex == NULL) | 
| 380 | greg | 1.1 | return(MG_EUNDEF); | 
| 381 |  |  | return(MG_OK); | 
| 382 |  |  | } | 
| 383 |  |  | if (av[2][0] != '=' || av[2][1]) | 
| 384 |  |  | return(MG_ETYPE); | 
| 385 | greg | 1.9 | if (c_cvertex == NULL) {        /* create new vertex context */ | 
| 386 | greg | 1.1 | lp->key = (char *)malloc(strlen(av[1])+1); | 
| 387 |  |  | if (lp->key == NULL) | 
| 388 |  |  | return(MG_EMEM); | 
| 389 |  |  | strcpy(lp->key, av[1]); | 
| 390 |  |  | lp->data = (char *)malloc(sizeof(C_VERTEX)); | 
| 391 |  |  | if (lp->data == NULL) | 
| 392 |  |  | return(MG_EMEM); | 
| 393 | greg | 1.14 | c_cvname = lp->key; | 
| 394 | greg | 1.9 | c_cvertex = (C_VERTEX *)lp->data; | 
| 395 | greg | 1.1 | } | 
| 396 | greg | 1.10 | i = c_cvertex->clock; | 
| 397 | greg | 1.1 | if (ac == 3) {          /* use default template */ | 
| 398 |  |  | *c_cvertex = c_dfvertex; | 
| 399 | greg | 1.9 | c_cvertex->clock = i + 1; | 
| 400 | greg | 1.1 | return(MG_OK); | 
| 401 |  |  | } | 
| 402 |  |  | lp = lu_find(&vtx_tab, av[3]);  /* lookup template */ | 
| 403 |  |  | if (lp == NULL) | 
| 404 |  |  | return(MG_EMEM); | 
| 405 |  |  | if (lp->data == NULL) | 
| 406 |  |  | return(MG_EUNDEF); | 
| 407 |  |  | *c_cvertex = *(C_VERTEX *)lp->data; | 
| 408 | greg | 1.9 | c_cvertex->clock = i + 1; | 
| 409 | greg | 1.1 | return(MG_OK); | 
| 410 |  |  | case MG_E_POINT:        /* set point */ | 
| 411 |  |  | if (ac != 4) | 
| 412 |  |  | return(MG_EARGC); | 
| 413 | greg | 1.18 | if (!isflt(av[1]) | !isflt(av[2]) | !isflt(av[3])) | 
| 414 | greg | 1.1 | return(MG_ETYPE); | 
| 415 |  |  | c_cvertex->p[0] = atof(av[1]); | 
| 416 |  |  | c_cvertex->p[1] = atof(av[2]); | 
| 417 |  |  | c_cvertex->p[2] = atof(av[3]); | 
| 418 | greg | 1.8 | c_cvertex->clock++; | 
| 419 | greg | 1.1 | return(MG_OK); | 
| 420 |  |  | case MG_E_NORMAL:       /* set normal */ | 
| 421 |  |  | if (ac != 4) | 
| 422 |  |  | return(MG_EARGC); | 
| 423 | greg | 1.18 | if (!isflt(av[1]) | !isflt(av[2]) | !isflt(av[3])) | 
| 424 | greg | 1.1 | return(MG_ETYPE); | 
| 425 |  |  | c_cvertex->n[0] = atof(av[1]); | 
| 426 |  |  | c_cvertex->n[1] = atof(av[2]); | 
| 427 |  |  | c_cvertex->n[2] = atof(av[3]); | 
| 428 |  |  | (void)normalize(c_cvertex->n); | 
| 429 | greg | 1.8 | c_cvertex->clock++; | 
| 430 | greg | 1.1 | return(MG_OK); | 
| 431 |  |  | } | 
| 432 |  |  | return(MG_EUNK); | 
| 433 |  |  | } | 
| 434 |  |  |  | 
| 435 |  |  |  | 
| 436 |  |  | void | 
| 437 |  |  | c_clearall()                    /* empty context tables */ | 
| 438 |  |  | { | 
| 439 |  |  | c_uncolor = c_dfcolor; | 
| 440 |  |  | c_ccolor = &c_uncolor; | 
| 441 | greg | 1.15 | c_ccname = NULL; | 
| 442 | greg | 1.3 | lu_done(&clr_tab); | 
| 443 | greg | 1.1 | c_unmaterial = c_dfmaterial; | 
| 444 |  |  | c_cmaterial = &c_unmaterial; | 
| 445 | greg | 1.15 | c_cmname = NULL; | 
| 446 | greg | 1.3 | lu_done(&mat_tab); | 
| 447 | greg | 1.1 | c_unvertex = c_dfvertex; | 
| 448 |  |  | c_cvertex = &c_unvertex; | 
| 449 | greg | 1.15 | c_cvname = NULL; | 
| 450 | greg | 1.3 | lu_done(&vtx_tab); | 
| 451 | greg | 1.1 | } | 
| 452 |  |  |  | 
| 453 |  |  |  | 
| 454 | greg | 1.11 | C_MATERIAL * | 
| 455 |  |  | c_getmaterial(name)             /* get a named material */ | 
| 456 |  |  | char    *name; | 
| 457 |  |  | { | 
| 458 |  |  | register LUENT  *lp; | 
| 459 |  |  |  | 
| 460 |  |  | if ((lp = lu_find(&mat_tab, name)) == NULL) | 
| 461 |  |  | return(NULL); | 
| 462 |  |  | return((C_MATERIAL *)lp->data); | 
| 463 |  |  | } | 
| 464 |  |  |  | 
| 465 |  |  |  | 
| 466 | greg | 1.1 | C_VERTEX * | 
| 467 |  |  | c_getvert(name)                 /* get a named vertex */ | 
| 468 |  |  | char    *name; | 
| 469 |  |  | { | 
| 470 |  |  | register LUENT  *lp; | 
| 471 |  |  |  | 
| 472 |  |  | if ((lp = lu_find(&vtx_tab, name)) == NULL) | 
| 473 |  |  | return(NULL); | 
| 474 |  |  | return((C_VERTEX *)lp->data); | 
| 475 | greg | 1.5 | } | 
| 476 |  |  |  | 
| 477 |  |  |  | 
| 478 | greg | 1.7 | C_COLOR * | 
| 479 |  |  | c_getcolor(name)                /* get a named color */ | 
| 480 |  |  | char    *name; | 
| 481 |  |  | { | 
| 482 |  |  | register LUENT  *lp; | 
| 483 |  |  |  | 
| 484 |  |  | if ((lp = lu_find(&clr_tab, name)) == NULL) | 
| 485 |  |  | return(NULL); | 
| 486 |  |  | return((C_COLOR *)lp->data); | 
| 487 |  |  | } | 
| 488 |  |  |  | 
| 489 |  |  |  | 
| 490 | greg | 1.5 | int | 
| 491 |  |  | c_isgrey(clr)                   /* check if color is grey */ | 
| 492 |  |  | register C_COLOR        *clr; | 
| 493 |  |  | { | 
| 494 | greg | 1.8 | if (!(clr->flags & (C_CSXY|C_CSSPEC))) | 
| 495 | greg | 1.5 | return(1);              /* no settings == grey */ | 
| 496 |  |  | c_ccvt(clr, C_CSXY); | 
| 497 |  |  | return(clr->cx >= .323 && clr->cx <= .343 && | 
| 498 |  |  | clr->cy >= .323 && clr->cy <= .343); | 
| 499 |  |  | } | 
| 500 |  |  |  | 
| 501 |  |  |  | 
| 502 |  |  | void | 
| 503 |  |  | c_ccvt(clr, fl)                 /* convert color representations */ | 
| 504 |  |  | register C_COLOR        *clr; | 
| 505 |  |  | int     fl; | 
| 506 |  |  | { | 
| 507 |  |  | double  x, y, z; | 
| 508 |  |  | register int    i; | 
| 509 |  |  |  | 
| 510 | greg | 1.16 | fl &= ~clr->flags;                      /* ignore what's done */ | 
| 511 |  |  | if (!fl)                                /* everything's done! */ | 
| 512 | greg | 1.5 | return; | 
| 513 | greg | 1.8 | if (!(clr->flags & (C_CSXY|C_CSSPEC)))  /* nothing set! */ | 
| 514 | greg | 1.5 | *clr = c_dfcolor; | 
| 515 | greg | 1.16 | if (fl & C_CSXY) {              /* cspec -> cxy */ | 
| 516 | greg | 1.5 | x = y = z = 0.; | 
| 517 |  |  | for (i = 0; i < C_CNSS; i++) { | 
| 518 |  |  | x += cie_xf.ssamp[i] * clr->ssamp[i]; | 
| 519 |  |  | y += cie_yf.ssamp[i] * clr->ssamp[i]; | 
| 520 |  |  | z += cie_zf.ssamp[i] * clr->ssamp[i]; | 
| 521 |  |  | } | 
| 522 | greg | 1.17 | x /= (double)cie_xf.ssum; | 
| 523 |  |  | y /= (double)cie_yf.ssum; | 
| 524 |  |  | z /= (double)cie_zf.ssum; | 
| 525 | greg | 1.5 | z += x + y; | 
| 526 |  |  | clr->cx = x / z; | 
| 527 |  |  | clr->cy = y / z; | 
| 528 |  |  | clr->flags |= C_CSXY; | 
| 529 | greg | 1.16 | } else if (fl & C_CSSPEC) {     /* cxy -> cspec */ | 
| 530 | greg | 1.19 | x = clr->cx; | 
| 531 |  |  | y = clr->cy; | 
| 532 |  |  | z = 1. - x - y; | 
| 533 | greg | 1.5 | clr->ssum = 0; | 
| 534 | greg | 1.19 | for (i = 0; i < C_CNSS; i++) { | 
| 535 |  |  | clr->ssamp[i] = x*cie_xp.ssamp[i] + y*cie_yp.ssamp[i] | 
| 536 |  |  | + z*cie_zp.ssamp[i] + .5; | 
| 537 |  |  | if (clr->ssamp[i] < 0)          /* out of gamut! */ | 
| 538 |  |  | clr->ssamp[i] = 0; | 
| 539 |  |  | else | 
| 540 |  |  | clr->ssum += clr->ssamp[i]; | 
| 541 |  |  | } | 
| 542 | greg | 1.5 | clr->flags |= C_CSSPEC; | 
| 543 |  |  | } | 
| 544 | greg | 1.16 | if (fl & C_CSEFF) {             /* compute efficacy */ | 
| 545 | greg | 1.19 | if (clr->flags & C_CSSPEC) {            /* from spectrum */ | 
| 546 | greg | 1.16 | y = 0.; | 
| 547 |  |  | for (i = 0; i < C_CNSS; i++) | 
| 548 |  |  | y += cie_yf.ssamp[i] * clr->ssamp[i]; | 
| 549 |  |  | clr->eff = C_CLPWM * y / clr->ssum; | 
| 550 | greg | 1.19 | } else /* clr->flags & C_CSXY */ {      /* from (x,y) */ | 
| 551 | greg | 1.16 | clr->eff = clr->cx*cie_xf.eff + clr->cy*cie_yf.eff + | 
| 552 |  |  | (1. - clr->cx - clr->cy)*cie_zf.eff; | 
| 553 |  |  | } | 
| 554 |  |  | clr->flags |= C_CSEFF; | 
| 555 |  |  | } | 
| 556 | greg | 1.5 | } | 
| 557 |  |  |  | 
| 558 |  |  |  | 
| 559 |  |  | static int | 
| 560 |  |  | setspectrum(clr, wlmin, wlmax, ac, av)  /* convert a spectrum */ | 
| 561 |  |  | register C_COLOR        *clr; | 
| 562 | greg | 1.17 | double  wlmin, wlmax; | 
| 563 | greg | 1.5 | int     ac; | 
| 564 |  |  | char    **av; | 
| 565 |  |  | { | 
| 566 |  |  | double  scale; | 
| 567 | greg | 1.17 | float   va[C_CNSS]; | 
| 568 |  |  | register int    i, pos; | 
| 569 |  |  | int     n, imax; | 
| 570 |  |  | int     wl; | 
| 571 | greg | 1.5 | double  wl0, wlstep; | 
| 572 | greg | 1.20 | double  boxpos, boxstep; | 
| 573 | greg | 1.17 | /* check bounds */ | 
| 574 |  |  | if (wlmax <= C_CMINWL | wlmax <= wlmin | wlmin >= C_CMAXWL) | 
| 575 | greg | 1.5 | return(MG_EILL); | 
| 576 | greg | 1.17 | wlstep = (wlmax - wlmin)/(ac-1); | 
| 577 |  |  | while (wlmin < C_CMINWL) { | 
| 578 |  |  | wlmin += wlstep; | 
| 579 |  |  | ac--; av++; | 
| 580 |  |  | } | 
| 581 |  |  | while (wlmax > C_CMAXWL) { | 
| 582 |  |  | wlmax -= wlstep; | 
| 583 |  |  | ac--; | 
| 584 |  |  | } | 
| 585 |  |  | imax = ac;                      /* box filter if necessary */ | 
| 586 | greg | 1.20 | boxpos = 0; | 
| 587 |  |  | boxstep = 1; | 
| 588 | greg | 1.17 | if (wlstep < C_CWLI) { | 
| 589 | greg | 1.20 | imax = (wlmax - wlmin)/C_CWLI + (1-FTINY); | 
| 590 |  |  | boxpos = (wlmin - C_CMINWL)/C_CWLI; | 
| 591 |  |  | boxstep = wlstep/C_CWLI; | 
| 592 | greg | 1.17 | wlstep = C_CWLI; | 
| 593 |  |  | } | 
| 594 | greg | 1.5 | scale = 0.;                     /* get values and maximum */ | 
| 595 | greg | 1.17 | pos = 0; | 
| 596 |  |  | for (i = 0; i < imax; i++) { | 
| 597 |  |  | va[i] = 0.; n = 0; | 
| 598 | greg | 1.20 | while (boxpos < i+.5 && pos < ac) { | 
| 599 | greg | 1.17 | if (!isflt(av[pos])) | 
| 600 |  |  | return(MG_ETYPE); | 
| 601 |  |  | va[i] += atof(av[pos++]); | 
| 602 |  |  | n++; | 
| 603 | greg | 1.20 | boxpos += boxstep; | 
| 604 | greg | 1.17 | } | 
| 605 |  |  | if (n > 1) | 
| 606 |  |  | va[i] /= (double)n; | 
| 607 | greg | 1.5 | if (va[i] > scale) | 
| 608 |  |  | scale = va[i]; | 
| 609 | greg | 1.23 | else if (va[i] < -scale) | 
| 610 |  |  | scale = -va[i]; | 
| 611 | greg | 1.5 | } | 
| 612 | greg | 1.20 | if (scale <= FTINY) | 
| 613 | greg | 1.5 | return(MG_EILL); | 
| 614 |  |  | scale = C_CMAXV / scale; | 
| 615 |  |  | clr->ssum = 0;                  /* convert to our spacing */ | 
| 616 |  |  | wl0 = wlmin; | 
| 617 |  |  | pos = 0; | 
| 618 |  |  | for (i = 0, wl = C_CMINWL; i < C_CNSS; i++, wl += C_CWLI) | 
| 619 | greg | 1.17 | if (wl < wlmin | wl > wlmax) | 
| 620 | greg | 1.5 | clr->ssamp[i] = 0; | 
| 621 |  |  | else { | 
| 622 |  |  | while (wl0 + wlstep < wl+FTINY) { | 
| 623 |  |  | wl0 += wlstep; | 
| 624 |  |  | pos++; | 
| 625 |  |  | } | 
| 626 | greg | 1.17 | if (wl+FTINY >= wl0 & wl-FTINY <= wl0) | 
| 627 | greg | 1.18 | clr->ssamp[i] = scale*va[pos] + .5; | 
| 628 | greg | 1.5 | else            /* interpolate if necessary */ | 
| 629 | greg | 1.18 | clr->ssamp[i] = .5 + scale / wlstep * | 
| 630 | greg | 1.5 | ( va[pos]*(wl0+wlstep - wl) + | 
| 631 |  |  | va[pos+1]*(wl - wl0) ); | 
| 632 |  |  | clr->ssum += clr->ssamp[i]; | 
| 633 |  |  | } | 
| 634 |  |  | clr->flags = C_CDSPEC|C_CSSPEC; | 
| 635 | greg | 1.8 | clr->clock++; | 
| 636 | greg | 1.5 | return(MG_OK); | 
| 637 |  |  | } | 
| 638 |  |  |  | 
| 639 |  |  |  | 
| 640 |  |  | static void | 
| 641 |  |  | mixcolors(cres, w1, c1, w2, c2) /* mix two colors according to weights given */ | 
| 642 |  |  | register C_COLOR        *cres, *c1, *c2; | 
| 643 |  |  | double  w1, w2; | 
| 644 |  |  | { | 
| 645 |  |  | double  scale; | 
| 646 |  |  | float   cmix[C_CNSS]; | 
| 647 |  |  | register int    i; | 
| 648 |  |  |  | 
| 649 |  |  | if ((c1->flags|c2->flags) & C_CDSPEC) {         /* spectral mixing */ | 
| 650 | greg | 1.16 | c_ccvt(c1, C_CSSPEC|C_CSEFF); | 
| 651 |  |  | c_ccvt(c2, C_CSSPEC|C_CSEFF); | 
| 652 |  |  | w1 /= c1->eff*c1->ssum; | 
| 653 | greg | 1.17 | w2 /= c2->eff*c2->ssum; | 
| 654 | greg | 1.5 | scale = 0.; | 
| 655 |  |  | for (i = 0; i < C_CNSS; i++) { | 
| 656 |  |  | cmix[i] = w1*c1->ssamp[i] + w2*c2->ssamp[i]; | 
| 657 |  |  | if (cmix[i] > scale) | 
| 658 |  |  | scale = cmix[i]; | 
| 659 |  |  | } | 
| 660 |  |  | scale = C_CMAXV / scale; | 
| 661 |  |  | cres->ssum = 0; | 
| 662 |  |  | for (i = 0; i < C_CNSS; i++) | 
| 663 |  |  | cres->ssum += cres->ssamp[i] = scale*cmix[i] + .5; | 
| 664 |  |  | cres->flags = C_CDSPEC|C_CSSPEC; | 
| 665 |  |  | } else {                                        /* CIE xy mixing */ | 
| 666 |  |  | c_ccvt(c1, C_CSXY); | 
| 667 |  |  | c_ccvt(c2, C_CSXY); | 
| 668 | greg | 1.24 | scale = w1/c1->cy + w2/c2->cy; | 
| 669 |  |  | if (scale == 0.) | 
| 670 |  |  | return; | 
| 671 |  |  | scale = 1. / scale; | 
| 672 | greg | 1.5 | cres->cx = (c1->cx*w1/c1->cy + c2->cx*w2/c2->cy) * scale; | 
| 673 |  |  | cres->cy = (w1 + w2) * scale; | 
| 674 |  |  | cres->flags = C_CDXY|C_CSXY; | 
| 675 |  |  | } | 
| 676 | greg | 1.1 | } | 
| 677 | greg | 1.18 |  | 
| 678 |  |  |  | 
| 679 |  |  | #define C1              3.741832e-16    /* W-m^2 */ | 
| 680 |  |  | #define C2              1.4388e-2       /* m-K */ | 
| 681 |  |  |  | 
| 682 |  |  | #define bbsp(l,t)       (C1/((l)*(l)*(l)*(l)*(l)*(exp(C2/((t)*(l)))-1.))) | 
| 683 |  |  | #define bblm(t)         (C2/5./(t)) | 
| 684 |  |  |  | 
| 685 |  |  | static int | 
| 686 |  |  | setbbtemp(clr, tk)              /* set black body spectrum */ | 
| 687 |  |  | register C_COLOR        *clr; | 
| 688 |  |  | double  tk; | 
| 689 |  |  | { | 
| 690 |  |  | double  sf, wl; | 
| 691 |  |  | register int    i; | 
| 692 |  |  |  | 
| 693 |  |  | if (tk < 1000) | 
| 694 |  |  | return(MG_EILL); | 
| 695 |  |  | wl = bblm(tk);                  /* scalefactor based on peak */ | 
| 696 |  |  | if (wl < C_CMINWL*1e-9) | 
| 697 |  |  | wl = C_CMINWL*1e-9; | 
| 698 |  |  | else if (wl > C_CMAXWL*1e-9) | 
| 699 |  |  | wl = C_CMAXWL*1e-9; | 
| 700 |  |  | sf = C_CMAXV/bbsp(wl,tk); | 
| 701 |  |  | clr->ssum = 0; | 
| 702 |  |  | for (i = 0; i < C_CNSS; i++) { | 
| 703 |  |  | wl = (C_CMINWL + i*C_CWLI)*1e-9; | 
| 704 |  |  | clr->ssum += clr->ssamp[i] = sf*bbsp(wl,tk) + .5; | 
| 705 |  |  | } | 
| 706 |  |  | clr->flags = C_CDSPEC|C_CSSPEC; | 
| 707 |  |  | clr->clock++; | 
| 708 |  |  | return(MG_OK); | 
| 709 |  |  | } | 
| 710 |  |  |  | 
| 711 |  |  | #undef  C1 | 
| 712 |  |  | #undef  C2 | 
| 713 |  |  | #undef  bbsp | 
| 714 |  |  | #undef  bblm |