| 1 | – | /* Copyright (c) 1991 Regents of the University of California */ | 
| 2 | – |  | 
| 1 |  | #ifndef lint | 
| 2 | < | static char SCCSid[] = "$SunId$ LBL"; | 
| 2 | > | static const char       RCSid[] = "$Id$"; | 
| 3 |  | #endif | 
| 6 | – |  | 
| 4 |  | /* | 
| 5 |  | * Routines to do the actual calculation for mkillum | 
| 6 |  | */ | 
| 7 |  |  | 
| 8 | < | #include  "mkillum.h" | 
| 8 | > | #include <string.h> | 
| 9 |  |  | 
| 10 | + | #include  "mkillum.h" | 
| 11 |  | #include  "face.h" | 
| 14 | – |  | 
| 12 |  | #include  "cone.h" | 
| 16 | – |  | 
| 13 |  | #include  "random.h" | 
| 14 |  |  | 
| 15 |  |  | 
| 16 | < | o_default(ob, il, rt, nm)       /* default illum action */ | 
| 17 | < | OBJREC  *ob; | 
| 18 | < | struct illum_args  *il; | 
| 19 | < | struct rtproc  *rt; | 
| 20 | < | char  *nm; | 
| 16 | > | int o_default(FUN_ARGLIST); | 
| 17 | > | int o_face(FUN_ARGLIST); | 
| 18 | > | int o_sphere(FUN_ARGLIST); | 
| 19 | > | int o_ring(FUN_ARGLIST); | 
| 20 | > | void raysamp(float res[3], FVECT org, FVECT dir, struct rtproc *rt); | 
| 21 | > | void rayflush(struct rtproc *rt); | 
| 22 | > | void mkaxes(FVECT u, FVECT v, FVECT n); | 
| 23 | > | void rounddir(FVECT dv, double alt, double azi); | 
| 24 | > | void flatdir(FVECT dv, double alt, double azi); | 
| 25 | > |  | 
| 26 | > |  | 
| 27 | > | int /* XXX type conflict with otypes.h */ | 
| 28 | > | o_default(      /* default illum action */ | 
| 29 | > | OBJREC  *ob, | 
| 30 | > | struct illum_args  *il, | 
| 31 | > | struct rtproc  *rt, | 
| 32 | > | char  *nm | 
| 33 | > | ) | 
| 34 |  | { | 
| 35 |  | sprintf(errmsg, "(%s): cannot make illum for %s \"%s\"", | 
| 36 |  | nm, ofun[ob->otype].funame, ob->oname); | 
| 37 |  | error(WARNING, errmsg); | 
| 38 | < | if (!(il->flags & IL_LIGHT)) | 
| 39 | < | printobj(il->altmat, ob); | 
| 38 | > | printobj(il->altmat, ob); | 
| 39 | > | return(1); | 
| 40 |  | } | 
| 41 |  |  | 
| 42 |  |  | 
| 43 | < | o_face(ob, il, rt, nm)          /* make an illum face */ | 
| 44 | < | OBJREC  *ob; | 
| 45 | < | struct illum_args  *il; | 
| 46 | < | struct rtproc  *rt; | 
| 47 | < | char  *nm; | 
| 43 | > | int | 
| 44 | > | o_face(         /* make an illum face */ | 
| 45 | > | OBJREC  *ob, | 
| 46 | > | struct illum_args  *il, | 
| 47 | > | struct rtproc  *rt, | 
| 48 | > | char  *nm | 
| 49 | > | ) | 
| 50 |  | { | 
| 51 |  | #define MAXMISS         (5*n*il->nsamps) | 
| 52 | < | int  dim[4]; | 
| 53 | < | int  n, nalt, nazi; | 
| 52 | > | int  dim[3]; | 
| 53 | > | int  n, nalt, nazi, h; | 
| 54 |  | float  *distarr; | 
| 55 | < | double  r1, r2; | 
| 55 | > | double  sp[2], r1, r2; | 
| 56 |  | FVECT  dn, org, dir; | 
| 57 |  | FVECT  u, v; | 
| 58 |  | double  ur[2], vr[2]; | 
| 63 |  | fa = getface(ob); | 
| 64 |  | if (fa->area == 0.0) { | 
| 65 |  | freeface(ob); | 
| 66 | < | o_default(ob, il, rt, nm); | 
| 56 | < | return; | 
| 66 | > | return(o_default(ob, il, rt, nm)); | 
| 67 |  | } | 
| 68 |  | /* set up sampling */ | 
| 69 | < | n = PI * il->sampdens; | 
| 70 | < | nalt = sqrt(n/PI) + .5; | 
| 71 | < | nazi = PI*nalt + .5; | 
| 69 | > | if (il->sampdens <= 0) | 
| 70 | > | nalt = nazi = 1; | 
| 71 | > | else { | 
| 72 | > | n = PI * il->sampdens; | 
| 73 | > | nalt = sqrt(n/PI) + .5; | 
| 74 | > | nazi = PI*nalt + .5; | 
| 75 | > | } | 
| 76 |  | n = nalt*nazi; | 
| 77 |  | distarr = (float *)calloc(n, 3*sizeof(float)); | 
| 78 |  | if (distarr == NULL) | 
| 79 |  | error(SYSTEM, "out of memory in o_face"); | 
| 80 | < | mkaxes(u, v, fa->norm); | 
| 80 | > | /* take first edge longer than sqrt(area) */ | 
| 81 | > | for (j = fa->nv-1, i = 0; i < fa->nv; j = i++) { | 
| 82 | > | u[0] = VERTEX(fa,i)[0] - VERTEX(fa,j)[0]; | 
| 83 | > | u[1] = VERTEX(fa,i)[1] - VERTEX(fa,j)[1]; | 
| 84 | > | u[2] = VERTEX(fa,i)[2] - VERTEX(fa,j)[2]; | 
| 85 | > | if ((r1 = DOT(u,u)) >= fa->area-FTINY) | 
| 86 | > | break; | 
| 87 | > | } | 
| 88 | > | if (i < fa->nv) {       /* got one! -- let's align our axes */ | 
| 89 | > | r2 = 1.0/sqrt(r1); | 
| 90 | > | u[0] *= r2; u[1] *= r2; u[2] *= r2; | 
| 91 | > | fcross(v, fa->norm, u); | 
| 92 | > | } else                  /* oh well, we'll just have to wing it */ | 
| 93 | > | mkaxes(u, v, fa->norm); | 
| 94 | > | /* now, find limits in (u,v) coordinates */ | 
| 95 |  | ur[0] = vr[0] = FHUGE; | 
| 96 |  | ur[1] = vr[1] = -FHUGE; | 
| 97 |  | for (i = 0; i < fa->nv; i++) { | 
| 109 |  | for (dim[2] = 0; dim[2] < nazi; dim[2]++) | 
| 110 |  | for (i = 0; i < il->nsamps; i++) { | 
| 111 |  | /* random direction */ | 
| 112 | < | dim[3] = 1; | 
| 113 | < | r1 = (dim[1]+urand(urind(ilhash(dim,4),i)))/nalt; | 
| 114 | < | dim[3] = 2; | 
| 115 | < | r2 = (dim[2]+urand(urind(ilhash(dim,4),i)))/nazi; | 
| 112 | > | h = ilhash(dim, 3) + i; | 
| 113 | > | multisamp(sp, 2, urand(h)); | 
| 114 | > | r1 = (dim[1] + sp[0])/nalt; | 
| 115 | > | r2 = (dim[2] + sp[1] - .5)/nazi; | 
| 116 |  | flatdir(dn, r1, r2); | 
| 117 |  | for (j = 0; j < 3; j++) | 
| 118 |  | dir[j] = -dn[0]*u[j] - dn[1]*v[j] - dn[2]*fa->norm[j]; | 
| 119 |  | /* random location */ | 
| 120 |  | do { | 
| 121 | < | dim[3] = 3; | 
| 122 | < | r1 = ur[0] + (ur[1]-ur[0]) * | 
| 123 | < | urand(urind(ilhash(dim,4),i+nmisses)); | 
| 96 | < | dim[3] = 4; | 
| 97 | < | r2 = vr[0] + (vr[1]-vr[0]) * | 
| 98 | < | urand(urind(ilhash(dim,4),i+nmisses)); | 
| 121 | > | multisamp(sp, 2, urand(h+4862+nmisses)); | 
| 122 | > | r1 = ur[0] + (ur[1]-ur[0]) * sp[0]; | 
| 123 | > | r2 = vr[0] + (vr[1]-vr[0]) * sp[1]; | 
| 124 |  | for (j = 0; j < 3; j++) | 
| 125 |  | org[j] = r1*u[j] + r2*v[j] | 
| 126 |  | + fa->offset*fa->norm[j]; | 
| 129 |  | objerror(ob, WARNING, "bad aspect"); | 
| 130 |  | rt->nrays = 0; | 
| 131 |  | freeface(ob); | 
| 132 | < | free((char *)distarr); | 
| 133 | < | o_default(ob, il, rt, nm); | 
| 109 | < | return; | 
| 132 | > | free((void *)distarr); | 
| 133 | > | return(o_default(ob, il, rt, nm)); | 
| 134 |  | } | 
| 135 |  | for (j = 0; j < 3; j++) | 
| 136 |  | org[j] += .001*fa->norm[j]; | 
| 138 |  | raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt); | 
| 139 |  | } | 
| 140 |  | rayflush(rt); | 
| 141 | < | /* write out the face w/ distribution */ | 
| 142 | < | flatout(il, distarr, nalt, nazi, u, v, fa->norm); | 
| 143 | < | illumout(il, ob); | 
| 141 | > | /* write out the face and its distribution */ | 
| 142 | > | if (average(il, distarr, nalt*nazi)) { | 
| 143 | > | if (il->sampdens > 0) | 
| 144 | > | flatout(il, distarr, nalt, nazi, u, v, fa->norm); | 
| 145 | > | illumout(il, ob); | 
| 146 | > | } else | 
| 147 | > | printobj(il->altmat, ob); | 
| 148 |  | /* clean up */ | 
| 149 |  | freeface(ob); | 
| 150 | < | free((char *)distarr); | 
| 150 | > | free((void *)distarr); | 
| 151 |  | #undef MAXMISS | 
| 152 | + | /* XXX we need to return something here. what is it? */ | 
| 153 |  | } | 
| 154 |  |  | 
| 155 |  |  | 
| 156 | < | o_sphere(ob, il, rt, nm)        /* make an illum sphere */ | 
| 157 | < | register OBJREC  *ob; | 
| 158 | < | struct illum_args  *il; | 
| 159 | < | struct rtproc  *rt; | 
| 160 | < | char  *nm; | 
| 156 | > | int | 
| 157 | > | o_sphere(       /* make an illum sphere */ | 
| 158 | > | register OBJREC  *ob, | 
| 159 | > | struct illum_args  *il, | 
| 160 | > | struct rtproc  *rt, | 
| 161 | > | char  *nm | 
| 162 | > | ) | 
| 163 |  | { | 
| 164 | < | int  dim[4]; | 
| 164 | > | int  dim[3]; | 
| 165 |  | int  n, nalt, nazi; | 
| 166 |  | float  *distarr; | 
| 167 | < | double  r1, r2, r3; | 
| 167 | > | double  sp[4], r1, r2, r3; | 
| 168 |  | FVECT  org, dir; | 
| 169 |  | FVECT  u, v; | 
| 170 |  | register int  i, j; | 
| 172 |  | if (ob->oargs.nfargs != 4) | 
| 173 |  | objerror(ob, USER, "bad # of arguments"); | 
| 174 |  | /* set up sampling */ | 
| 175 | < | n = 4.*PI * il->sampdens; | 
| 176 | < | nalt = sqrt(n/PI) + .5; | 
| 177 | < | nazi = PI*nalt + .5; | 
| 175 | > | if (il->sampdens <= 0) | 
| 176 | > | nalt = nazi = 1; | 
| 177 | > | else { | 
| 178 | > | n = 4.*PI * il->sampdens; | 
| 179 | > | nalt = sqrt(2./PI*n) + .5; | 
| 180 | > | nazi = PI/2.*nalt + .5; | 
| 181 | > | } | 
| 182 |  | n = nalt*nazi; | 
| 183 |  | distarr = (float *)calloc(n, 3*sizeof(float)); | 
| 184 |  | if (distarr == NULL) | 
| 188 |  | for (dim[1] = 0; dim[1] < nalt; dim[1]++) | 
| 189 |  | for (dim[2] = 0; dim[2] < nazi; dim[2]++) | 
| 190 |  | for (i = 0; i < il->nsamps; i++) { | 
| 191 | + | /* next sample point */ | 
| 192 | + | multisamp(sp, 4, urand(ilhash(dim,3)+i)); | 
| 193 |  | /* random direction */ | 
| 194 | < | dim[3] = 1; | 
| 195 | < | r1 = (dim[1]+urand(urind(ilhash(dim,4),i)))/nalt; | 
| 159 | < | dim[3] = 2; | 
| 160 | < | r2 = (dim[2]+urand(urind(ilhash(dim,4),i)))/nazi; | 
| 194 | > | r1 = (dim[1] + sp[0])/nalt; | 
| 195 | > | r2 = (dim[2] + sp[1] - .5)/nazi; | 
| 196 |  | rounddir(dir, r1, r2); | 
| 197 |  | /* random location */ | 
| 198 |  | mkaxes(u, v, dir);          /* yuck! */ | 
| 199 | < | dim[3] = 3; | 
| 200 | < | r3 = sqrt(urand(urind(ilhash(dim,4),i))); | 
| 166 | < | dim[3] = 4; | 
| 167 | < | r2 = 2.*PI*urand(urind(ilhash(dim,4),i)); | 
| 199 | > | r3 = sqrt(sp[2]); | 
| 200 | > | r2 = 2.*PI*sp[3]; | 
| 201 |  | r1 = r3*ob->oargs.farg[3]*cos(r2); | 
| 202 |  | r2 = r3*ob->oargs.farg[3]*sin(r2); | 
| 203 |  | r3 = ob->oargs.farg[3]*sqrt(1.01-r3*r3); | 
| 210 |  | raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt); | 
| 211 |  | } | 
| 212 |  | rayflush(rt); | 
| 213 | < | /* write out the sphere w/ distribution */ | 
| 214 | < | roundout(il, distarr, nalt, nazi); | 
| 215 | < | illumout(il, ob); | 
| 213 | > | /* write out the sphere and its distribution */ | 
| 214 | > | if (average(il, distarr, nalt*nazi)) { | 
| 215 | > | if (il->sampdens > 0) | 
| 216 | > | roundout(il, distarr, nalt, nazi); | 
| 217 | > | else | 
| 218 | > | objerror(ob, WARNING, "diffuse distribution"); | 
| 219 | > | illumout(il, ob); | 
| 220 | > | } else | 
| 221 | > | printobj(il->altmat, ob); | 
| 222 |  | /* clean up */ | 
| 223 | < | free((char *)distarr); | 
| 223 | > | free((void *)distarr); | 
| 224 | > | return(1); | 
| 225 |  | } | 
| 226 |  |  | 
| 227 |  |  | 
| 228 | < | o_ring(ob, il, rt, nm)          /* make an illum ring */ | 
| 229 | < | OBJREC  *ob; | 
| 230 | < | struct illum_args  *il; | 
| 231 | < | struct rtproc  *rt; | 
| 232 | < | char  *nm; | 
| 228 | > | int | 
| 229 | > | o_ring(         /* make an illum ring */ | 
| 230 | > | OBJREC  *ob, | 
| 231 | > | struct illum_args  *il, | 
| 232 | > | struct rtproc  *rt, | 
| 233 | > | char  *nm | 
| 234 | > | ) | 
| 235 |  | { | 
| 236 | < | int  dim[4]; | 
| 236 | > | int  dim[3]; | 
| 237 |  | int  n, nalt, nazi; | 
| 238 |  | float  *distarr; | 
| 239 | < | double  r1, r2, r3; | 
| 239 | > | double  sp[4], r1, r2, r3; | 
| 240 |  | FVECT  dn, org, dir; | 
| 241 |  | FVECT  u, v; | 
| 242 |  | register CONE  *co; | 
| 244 |  | /* get/check arguments */ | 
| 245 |  | co = getcone(ob, 0); | 
| 246 |  | /* set up sampling */ | 
| 247 | < | n = PI * il->sampdens; | 
| 248 | < | nalt = sqrt(n/PI) + .5; | 
| 249 | < | nazi = PI*nalt + .5; | 
| 247 | > | if (il->sampdens <= 0) | 
| 248 | > | nalt = nazi = 1; | 
| 249 | > | else { | 
| 250 | > | n = PI * il->sampdens; | 
| 251 | > | nalt = sqrt(n/PI) + .5; | 
| 252 | > | nazi = PI*nalt + .5; | 
| 253 | > | } | 
| 254 |  | n = nalt*nazi; | 
| 255 |  | distarr = (float *)calloc(n, 3*sizeof(float)); | 
| 256 |  | if (distarr == NULL) | 
| 261 |  | for (dim[1] = 0; dim[1] < nalt; dim[1]++) | 
| 262 |  | for (dim[2] = 0; dim[2] < nazi; dim[2]++) | 
| 263 |  | for (i = 0; i < il->nsamps; i++) { | 
| 264 | + | /* next sample point */ | 
| 265 | + | multisamp(sp, 4, urand(ilhash(dim,3)+i)); | 
| 266 |  | /* random direction */ | 
| 267 | < | dim[3] = 1; | 
| 268 | < | r1 = (dim[1]+urand(urind(ilhash(dim,4),i)))/nalt; | 
| 221 | < | dim[3] = 2; | 
| 222 | < | r2 = (dim[2]+urand(urind(ilhash(dim,4),i)))/nalt; | 
| 267 | > | r1 = (dim[1] + sp[0])/nalt; | 
| 268 | > | r2 = (dim[2] + sp[1] - .5)/nazi; | 
| 269 |  | flatdir(dn, r1, r2); | 
| 270 |  | for (j = 0; j < 3; j++) | 
| 271 |  | dir[j] = -dn[0]*u[j] - dn[1]*v[j] - dn[2]*co->ad[j]; | 
| 272 |  | /* random location */ | 
| 227 | – | dim[3] = 3; | 
| 273 |  | r3 = sqrt(CO_R0(co)*CO_R0(co) + | 
| 274 | < | urand(urind(ilhash(dim,4),i))* | 
| 275 | < | (CO_R1(co)*CO_R1(co) - CO_R0(co)*CO_R0(co))); | 
| 231 | < | dim[3] = 4; | 
| 232 | < | r2 = 2.*PI*urand(urind(ilhash(dim,4),i)); | 
| 274 | > | sp[2]*(CO_R1(co)*CO_R1(co) - CO_R0(co)*CO_R0(co))); | 
| 275 | > | r2 = 2.*PI*sp[3]; | 
| 276 |  | r1 = r3*cos(r2); | 
| 277 |  | r2 = r3*sin(r2); | 
| 278 |  | for (j = 0; j < 3; j++) | 
| 279 | < | org[j] = CO_P0(co)[j] + r1*u[j] + r1*v[j] + | 
| 279 | > | org[j] = CO_P0(co)[j] + r1*u[j] + r2*v[j] + | 
| 280 |  | .001*co->ad[j]; | 
| 281 |  |  | 
| 282 |  | /* send sample */ | 
| 283 |  | raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt); | 
| 284 |  | } | 
| 285 |  | rayflush(rt); | 
| 286 | < | /* write out the ring w/ distribution */ | 
| 287 | < | flatout(il, distarr, nalt, nazi, u, v, co->ad); | 
| 288 | < | illumout(il, ob); | 
| 286 | > | /* write out the ring and its distribution */ | 
| 287 | > | if (average(il, distarr, nalt*nazi)) { | 
| 288 | > | if (il->sampdens > 0) | 
| 289 | > | flatout(il, distarr, nalt, nazi, u, v, co->ad); | 
| 290 | > | illumout(il, ob); | 
| 291 | > | } else | 
| 292 | > | printobj(il->altmat, ob); | 
| 293 |  | /* clean up */ | 
| 294 |  | freecone(ob); | 
| 295 | < | free((char *)distarr); | 
| 295 | > | free((void *)distarr); | 
| 296 | > | return(1); | 
| 297 |  | } | 
| 298 |  |  | 
| 299 |  |  | 
| 300 | < | raysamp(res, org, dir, rt)      /* compute a ray sample */ | 
| 301 | < | float  res[3]; | 
| 302 | < | FVECT  org, dir; | 
| 303 | < | register struct rtproc  *rt; | 
| 300 | > | void | 
| 301 | > | raysamp(        /* compute a ray sample */ | 
| 302 | > | float  res[3], | 
| 303 | > | FVECT  org, | 
| 304 | > | FVECT  dir, | 
| 305 | > | register struct rtproc  *rt | 
| 306 | > | ) | 
| 307 |  | { | 
| 308 |  | register float  *fp; | 
| 309 |  |  | 
| 316 |  | } | 
| 317 |  |  | 
| 318 |  |  | 
| 319 | < | rayflush(rt)                    /* flush buffered rays */ | 
| 320 | < | register struct rtproc  *rt; | 
| 319 | > | void | 
| 320 | > | rayflush(                       /* flush buffered rays */ | 
| 321 | > | register struct rtproc  *rt | 
| 322 | > | ) | 
| 323 |  | { | 
| 324 |  | register int  i; | 
| 325 |  |  | 
| 326 |  | if (rt->nrays <= 0) | 
| 327 |  | return; | 
| 328 | < | bzero(rt->buf+6*rt->nrays, 6*sizeof(float)); | 
| 329 | < | if ( process(rt->pd, (char *)rt->buf, (char *)rt->buf, | 
| 330 | < | 3*sizeof(float)*rt->nrays, | 
| 328 | > | memset(rt->buf+6*rt->nrays, '\0', 6*sizeof(float)); | 
| 329 | > | errno = 0; | 
| 330 | > | if ( process(&(rt->pd), (char *)rt->buf, (char *)rt->buf, | 
| 331 | > | 3*sizeof(float)*(rt->nrays+1), | 
| 332 |  | 6*sizeof(float)*(rt->nrays+1)) < | 
| 333 | < | 3*sizeof(float)*rt->nrays ) | 
| 333 | > | 3*sizeof(float)*(rt->nrays+1) ) | 
| 334 |  | error(SYSTEM, "error reading from rtrace process"); | 
| 335 |  | i = rt->nrays; | 
| 336 |  | while (i--) { | 
| 342 |  | } | 
| 343 |  |  | 
| 344 |  |  | 
| 345 | < | mkaxes(u, v, n)                 /* compute u and v to go with n */ | 
| 346 | < | FVECT  u, v, n; | 
| 345 | > | void | 
| 346 | > | mkaxes(                 /* compute u and v to go with n */ | 
| 347 | > | FVECT  u, | 
| 348 | > | FVECT  v, | 
| 349 | > | FVECT  n | 
| 350 | > | ) | 
| 351 |  | { | 
| 352 |  | register int  i; | 
| 353 |  |  | 
| 362 |  | } | 
| 363 |  |  | 
| 364 |  |  | 
| 365 | < | rounddir(dv, alt, azi)          /* compute uniform spherical direction */ | 
| 366 | < | register FVECT  dv; | 
| 367 | < | double  alt, azi; | 
| 365 | > | void | 
| 366 | > | rounddir(               /* compute uniform spherical direction */ | 
| 367 | > | register FVECT  dv, | 
| 368 | > | double  alt, | 
| 369 | > | double  azi | 
| 370 | > | ) | 
| 371 |  | { | 
| 372 |  | double  d1, d2; | 
| 373 |  |  | 
| 379 |  | } | 
| 380 |  |  | 
| 381 |  |  | 
| 382 | < | flatdir(dv, alt, azi)           /* compute uniform hemispherical direction */ | 
| 383 | < | register FVECT  dv; | 
| 384 | < | double  alt, azi; | 
| 382 | > | void | 
| 383 | > | flatdir(                /* compute uniform hemispherical direction */ | 
| 384 | > | register FVECT  dv, | 
| 385 | > | double  alt, | 
| 386 | > | double  azi | 
| 387 | > | ) | 
| 388 |  | { | 
| 389 |  | double  d1, d2; | 
| 390 |  |  |