| 1 | #ifndef lint | 
| 2 | static const char       RCSid[] = "$Id: rglmat.c,v 3.6 2003/11/14 17:22:06 schorsch Exp $"; | 
| 3 | #endif | 
| 4 | /* | 
| 5 | * Routines for Radiance -> OpenGL materials. | 
| 6 | */ | 
| 7 |  | 
| 8 | #include "copyright.h" | 
| 9 |  | 
| 10 | #include "radogl.h" | 
| 11 |  | 
| 12 | int     domats = 1;                     /* are we doing materials? */ | 
| 13 |  | 
| 14 | extern lut_free_t       freemtl; | 
| 15 |  | 
| 16 | LUTAB   mtab = LU_SINIT(free,freemtl); | 
| 17 |  | 
| 18 |  | 
| 19 | void | 
| 20 | rgl_matclear(void)                      /* clean up materials */ | 
| 21 | { | 
| 22 | lu_done(&mtab); | 
| 23 | domats = 1; | 
| 24 | } | 
| 25 |  | 
| 26 |  | 
| 27 | MATREC * | 
| 28 | getmatp(                        /* find material record for modifier name */ | 
| 29 | char    *nam | 
| 30 | ) | 
| 31 | { | 
| 32 | register LUENT  *lup; | 
| 33 |  | 
| 34 | if (nam == NULL) | 
| 35 | return(NULL); | 
| 36 | if ((lup = lu_find(&mtab, nam)) == NULL) | 
| 37 | return(NULL); | 
| 38 | return((MATREC *)lup->data); | 
| 39 | } | 
| 40 |  | 
| 41 |  | 
| 42 | int | 
| 43 | o_default(                      /* default object is non-material modifier */ | 
| 44 | register OBJREC *o | 
| 45 | ) | 
| 46 | { | 
| 47 | register LUENT  *lup; | 
| 48 | #ifdef DEBUG | 
| 49 | if (o->otype >= 0 && !ismodifier(o->otype)) | 
| 50 | error(CONSISTENCY, "o_default handed non-modifier"); | 
| 51 | #endif | 
| 52 | /* find name in lookup table */ | 
| 53 | if ((lup = lu_find(&mtab, o->oname)) == NULL) | 
| 54 | goto memerr; | 
| 55 | if (lup->key == NULL) {         /* new entry? */ | 
| 56 | lup->key = (char *)malloc(strlen(o->oname)+1); | 
| 57 | if (lup->key == NULL) | 
| 58 | goto memerr; | 
| 59 | strcpy(lup->key, o->oname); | 
| 60 | } else if (lup->data != NULL) | 
| 61 | freemtl(lup->data); | 
| 62 | if ((lup->data = o->os) != NULL)        /* make material reference */ | 
| 63 | ((MATREC *)lup->data)->nlinks++; | 
| 64 | return(0); | 
| 65 | memerr: | 
| 66 | error(SYSTEM, "out of memory in o_default"); | 
| 67 | return(0); | 
| 68 | } | 
| 69 |  | 
| 70 |  | 
| 71 | int | 
| 72 | o_unsupported(          /* unsupported object primitive */ | 
| 73 | OBJREC  *o | 
| 74 | ) | 
| 75 | { | 
| 76 | objerror(o, WARNING, "unsupported type"); | 
| 77 | return(0); | 
| 78 | } | 
| 79 |  | 
| 80 |  | 
| 81 | MATREC * | 
| 82 | newmaterial(            /* get an entry for a new material */ | 
| 83 | char    *nam | 
| 84 | ) | 
| 85 | { | 
| 86 | register LUENT  *lup; | 
| 87 | /* look it up (assign entry) */ | 
| 88 | if ((lup = lu_find(&mtab, nam)) == NULL) | 
| 89 | goto memerr; | 
| 90 | if (lup->key == NULL) {         /* new entry? */ | 
| 91 | lup->key = (char *)malloc(strlen(nam)+1); | 
| 92 | if (lup->key == NULL) | 
| 93 | goto memerr; | 
| 94 | strcpy(lup->key, nam); | 
| 95 | } else if (lup->data != NULL) | 
| 96 | freemtl(lup->data); | 
| 97 | lup->data = (char *)malloc(sizeof(MATREC)); | 
| 98 | if (lup->data == NULL) | 
| 99 | goto memerr; | 
| 100 | ((MATREC *)lup->data)->nlinks = 1; | 
| 101 | return((MATREC *)lup->data); | 
| 102 | memerr: | 
| 103 | error(SYSTEM, "out of memory in newmaterial"); | 
| 104 | return NULL; /* pro forma return */ | 
| 105 | } | 
| 106 |  | 
| 107 |  | 
| 108 | void | 
| 109 | freemtl(void *p)                /* free a material */ | 
| 110 | { | 
| 111 | register MATREC *mp = (MATREC *)p; | 
| 112 |  | 
| 113 | if (!--mp->nlinks) | 
| 114 | free((void *)mp); | 
| 115 | } | 
| 116 |  | 
| 117 |  | 
| 118 | int | 
| 119 | m_normal(                       /* compute normal material parameters */ | 
| 120 | register OBJREC *o | 
| 121 | ) | 
| 122 | { | 
| 123 | register MATREC *m; | 
| 124 | /* check arguments */ | 
| 125 | if (o->oargs.nfargs != (o->otype == MAT_TRANS ? 7 : 5)) | 
| 126 | objerror(o, USER, "bad # of real arguments"); | 
| 127 | /* allocate/insert material */ | 
| 128 | m = newmaterial(o->oname); | 
| 129 | /* assign parameters */ | 
| 130 | setcolor(m->u.m.ambdiff, o->oargs.farg[0], | 
| 131 | o->oargs.farg[1], o->oargs.farg[2]); | 
| 132 | if ((m->type = o->otype) == MAT_METAL) | 
| 133 | copycolor(m->u.m.specular, m->u.m.ambdiff); | 
| 134 | else | 
| 135 | setcolor(m->u.m.specular, 1., 1., 1.); | 
| 136 | scalecolor(m->u.m.specular, o->oargs.farg[3]); | 
| 137 | scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[3]); | 
| 138 | if (m->type == MAT_TRANS) { | 
| 139 | scalecolor(m->u.m.specular, 1.-o->oargs.farg[5]); | 
| 140 | scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[5]); | 
| 141 | } | 
| 142 | if (o->oargs.farg[4] <= FTINY) | 
| 143 | m->u.m.specexp = MAXSPECEXP; | 
| 144 | else | 
| 145 | m->u.m.specexp = 2./(o->oargs.farg[4]*o->oargs.farg[4]); | 
| 146 | if (m->u.m.specexp > MAXSPECEXP) | 
| 147 | m->u.m.specexp = MAXSPECEXP; | 
| 148 | return(0); | 
| 149 | } | 
| 150 |  | 
| 151 |  | 
| 152 | int | 
| 153 | m_aniso(                        /* anisotropic material */ | 
| 154 | register OBJREC *o | 
| 155 | ) | 
| 156 | { | 
| 157 | register MATREC *m; | 
| 158 | /* check arguments */ | 
| 159 | if (o->oargs.nfargs < (o->otype == MAT_TRANS2 ? 8 : 6)) | 
| 160 | objerror(o, USER, "bad # of real arguments"); | 
| 161 | /* allocate/insert material */ | 
| 162 | m = newmaterial(o->oname); | 
| 163 | /* assign parameters */ | 
| 164 | setcolor(m->u.m.ambdiff, o->oargs.farg[0], | 
| 165 | o->oargs.farg[1], o->oargs.farg[2]); | 
| 166 | if ((m->type = o->otype) == MAT_METAL2) | 
| 167 | copycolor(m->u.m.specular, m->u.m.ambdiff); | 
| 168 | else | 
| 169 | setcolor(m->u.m.specular, 1., 1., 1.); | 
| 170 | scalecolor(m->u.m.specular, o->oargs.farg[3]); | 
| 171 | scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[3]); | 
| 172 | if (m->type == MAT_TRANS2) { | 
| 173 | scalecolor(m->u.m.specular, 1.-o->oargs.farg[6]); | 
| 174 | scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[6]); | 
| 175 | } | 
| 176 | if (o->oargs.farg[4]*o->oargs.farg[5] <= FTINY*FTINY) | 
| 177 | m->u.m.specexp = MAXSPECEXP; | 
| 178 | else | 
| 179 | m->u.m.specexp = 2./(o->oargs.farg[4]*o->oargs.farg[5]); | 
| 180 | if (m->u.m.specexp > MAXSPECEXP) | 
| 181 | m->u.m.specexp = MAXSPECEXP; | 
| 182 | return(0); | 
| 183 | } | 
| 184 |  | 
| 185 |  | 
| 186 | int | 
| 187 | m_glass(                        /* glass material (hopeless) */ | 
| 188 | OBJREC  *o | 
| 189 | ) | 
| 190 | { | 
| 191 | register MATREC *m; | 
| 192 |  | 
| 193 | m = newmaterial(o->oname); | 
| 194 | m->type = o->otype; | 
| 195 | setcolor(m->u.m.ambdiff, 0., 0., 0.); | 
| 196 | setcolor(m->u.m.specular, .08, .08, .08); | 
| 197 | m->u.m.specexp = MAXSPECEXP; | 
| 198 | return(0); | 
| 199 | } | 
| 200 |  | 
| 201 |  | 
| 202 | int | 
| 203 | m_brdf(o)                       /* convert functional material */ | 
| 204 | register OBJREC *o; | 
| 205 | { | 
| 206 | register MATREC *m; | 
| 207 | /* check arguments */ | 
| 208 | if (o->oargs.nfargs < (o->otype == MAT_TFUNC ? 6 : 4)) | 
| 209 | objerror(o, USER, "bad # of real arguments"); | 
| 210 | /* allocate/insert material */ | 
| 211 | m = newmaterial(o->oname); | 
| 212 | /* assign parameters */ | 
| 213 | setcolor(m->u.m.ambdiff, o->oargs.farg[0], | 
| 214 | o->oargs.farg[1], o->oargs.farg[2]); | 
| 215 | if ((m->type = o->otype) == MAT_MFUNC) | 
| 216 | copycolor(m->u.m.specular, m->u.m.ambdiff); | 
| 217 | else | 
| 218 | setcolor(m->u.m.specular, 1., 1., 1.); | 
| 219 | scalecolor(m->u.m.specular, o->oargs.farg[3]); | 
| 220 | scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[3]); | 
| 221 | if (m->type == MAT_TFUNC) { | 
| 222 | scalecolor(m->u.m.specular, 1.-o->oargs.farg[4]); | 
| 223 | scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[4]); | 
| 224 | } | 
| 225 | m->u.m.specexp = UNKSPECEXP; | 
| 226 | return(0); | 
| 227 | } | 
| 228 |  | 
| 229 |  | 
| 230 | int | 
| 231 | m_brdf2(o)                      /* convert advanced functional material */ | 
| 232 | register OBJREC *o; | 
| 233 | { | 
| 234 | register MATREC *m; | 
| 235 |  | 
| 236 | if (o->oargs.nfargs < 9) | 
| 237 | objerror(o, USER, "bad # of real arguments"); | 
| 238 | m = newmaterial(o->oname); | 
| 239 | m->type = o->otype; | 
| 240 | /* assign average diffuse front+back */ | 
| 241 | setcolor(m->u.m.ambdiff, (o->oargs.farg[0]+o->oargs.farg[3])*.5, | 
| 242 | (o->oargs.farg[1]+o->oargs.farg[4])*.5, | 
| 243 | (o->oargs.farg[2]+o->oargs.farg[5])*.5); | 
| 244 | /* guess the rest */ | 
| 245 | setcolor(m->u.m.specular, .1, .1, .1); | 
| 246 | m->u.m.specexp = UNKSPECEXP; | 
| 247 | return(0); | 
| 248 | } | 
| 249 |  | 
| 250 |  | 
| 251 | int | 
| 252 | m_light(o)                      /* convert light type */ | 
| 253 | register OBJREC *o; | 
| 254 | { | 
| 255 | FVECT   v; | 
| 256 | register MATREC *m; | 
| 257 |  | 
| 258 | if (o->oargs.nfargs < (o->otype == MAT_SPOT ? 7 : 3)) | 
| 259 | objerror(o, USER, "bad # of real arguments"); | 
| 260 | m = newmaterial(o->oname); | 
| 261 | setcolor(m->u.l.emission, o->oargs.farg[0], | 
| 262 | o->oargs.farg[1], o->oargs.farg[2]); | 
| 263 | if ((m->type = o->otype) == MAT_SPOT) { | 
| 264 | if ((m->u.l.spotang = o->oargs.farg[3]/2.) > 90.) | 
| 265 | m->u.l.spotang = 180.; | 
| 266 | v[0] = o->oargs.farg[4]; | 
| 267 | v[1] = o->oargs.farg[5]; | 
| 268 | v[2] = o->oargs.farg[6]; | 
| 269 | if (normalize(v) == 0.) | 
| 270 | objerror(o, USER, "illegal direction"); | 
| 271 | VCOPY(m->u.l.spotdir, v); | 
| 272 | } else { | 
| 273 | m->u.l.spotang = 180.; | 
| 274 | m->u.l.spotdir[0] = m->u.l.spotdir[1] = 0.; | 
| 275 | m->u.l.spotdir[2] = -1.; | 
| 276 | } | 
| 277 | return(0); | 
| 278 | } | 
| 279 |  | 
| 280 |  | 
| 281 | int | 
| 282 | m_mirror(o)                     /* convert mirror type */ | 
| 283 | register OBJREC *o; | 
| 284 | { | 
| 285 | register MATREC *m; | 
| 286 |  | 
| 287 | if (o->oargs.nfargs != 3) | 
| 288 | objerror(o, USER, "bad # real arguments"); | 
| 289 | m = newmaterial(o->oname); | 
| 290 | m->type = o->otype; | 
| 291 | setcolor(m->u.m.ambdiff, 0., 0., 0.); | 
| 292 | setcolor(m->u.m.specular, o->oargs.farg[0], | 
| 293 | o->oargs.farg[1], o->oargs.farg[2]); | 
| 294 | m->u.m.specexp = MAXSPECEXP; | 
| 295 | return(0); | 
| 296 | } | 
| 297 |  | 
| 298 |  | 
| 299 | int | 
| 300 | m_prism(o)                      /* convert prism type */ | 
| 301 | register OBJREC *o; | 
| 302 | { | 
| 303 | register MATREC *m; | 
| 304 | /* can't really deal with this type */ | 
| 305 | m = newmaterial(o->oname); | 
| 306 | m->type = o->otype; | 
| 307 | setcolor(m->u.m.ambdiff, 0.2, 0.2, 0.2); | 
| 308 | setcolor(m->u.m.specular, 0.1, 0.1, 0.1); | 
| 309 | m->u.m.specexp = UNKSPECEXP; | 
| 310 | return(0); | 
| 311 | } |