| 1 | < | /* Copyright (c) 1991 Regents of the University of California */ | 
| 1 | > | /* Copyright (c) 1995 Regents of the University of California */ | 
| 2 |  |  | 
| 3 |  | #ifndef lint | 
| 4 |  | static char SCCSid[] = "$SunId$ LBL"; | 
| 26 |  | sprintf(errmsg, "(%s): cannot make illum for %s \"%s\"", | 
| 27 |  | nm, ofun[ob->otype].funame, ob->oname); | 
| 28 |  | error(WARNING, errmsg); | 
| 29 | < | if (!(il->flags & IL_LIGHT)) | 
| 30 | < | printobj(il->altmat, ob); | 
| 29 | > | printobj(il->altmat, ob); | 
| 30 |  | } | 
| 31 |  |  | 
| 32 |  |  | 
| 37 |  | char  *nm; | 
| 38 |  | { | 
| 39 |  | #define MAXMISS         (5*n*il->nsamps) | 
| 40 | < | int  dim[4]; | 
| 41 | < | int  n, nalt, nazi; | 
| 40 | > | int  dim[3]; | 
| 41 | > | int  n, nalt, nazi, h; | 
| 42 |  | float  *distarr; | 
| 43 | < | double  r1, r2; | 
| 43 | > | double  sp[2], r1, r2; | 
| 44 |  | FVECT  dn, org, dir; | 
| 45 |  | FVECT  u, v; | 
| 46 |  | double  ur[2], vr[2]; | 
| 55 |  | return; | 
| 56 |  | } | 
| 57 |  | /* set up sampling */ | 
| 58 | < | n = PI * il->sampdens; | 
| 59 | < | nalt = sqrt(n/PI) + .5; | 
| 60 | < | nazi = PI*nalt + .5; | 
| 58 | > | if (il->sampdens <= 0) | 
| 59 | > | nalt = nazi = 1; | 
| 60 | > | else { | 
| 61 | > | n = PI * il->sampdens; | 
| 62 | > | nalt = sqrt(n/PI) + .5; | 
| 63 | > | nazi = PI*nalt + .5; | 
| 64 | > | } | 
| 65 |  | n = nalt*nazi; | 
| 66 |  | distarr = (float *)calloc(n, 3*sizeof(float)); | 
| 67 |  | if (distarr == NULL) | 
| 68 |  | error(SYSTEM, "out of memory in o_face"); | 
| 69 | < | mkaxes(u, v, fa->norm); | 
| 69 | > | /* take first edge longer than sqrt(area) */ | 
| 70 | > | for (j = fa->nv-1, i = 0; i < fa->nv; j = i++) { | 
| 71 | > | u[0] = VERTEX(fa,i)[0] - VERTEX(fa,j)[0]; | 
| 72 | > | u[1] = VERTEX(fa,i)[1] - VERTEX(fa,j)[1]; | 
| 73 | > | u[2] = VERTEX(fa,i)[2] - VERTEX(fa,j)[2]; | 
| 74 | > | if ((r1 = DOT(u,u)) >= fa->area-FTINY) | 
| 75 | > | break; | 
| 76 | > | } | 
| 77 | > | if (i < fa->nv) {       /* got one! -- let's align our axes */ | 
| 78 | > | r2 = 1.0/sqrt(r1); | 
| 79 | > | u[0] *= r2; u[1] *= r2; u[2] *= r2; | 
| 80 | > | fcross(v, fa->norm, u); | 
| 81 | > | } else                  /* oh well, we'll just have to wing it */ | 
| 82 | > | mkaxes(u, v, fa->norm); | 
| 83 | > | /* now, find limits in (u,v) coordinates */ | 
| 84 |  | ur[0] = vr[0] = FHUGE; | 
| 85 |  | ur[1] = vr[1] = -FHUGE; | 
| 86 |  | for (i = 0; i < fa->nv; i++) { | 
| 98 |  | for (dim[2] = 0; dim[2] < nazi; dim[2]++) | 
| 99 |  | for (i = 0; i < il->nsamps; i++) { | 
| 100 |  | /* random direction */ | 
| 101 | < | dim[3] = 1; | 
| 102 | < | r1 = (dim[1]+urand(urind(ilhash(dim,4),i)))/nalt; | 
| 103 | < | dim[3] = 2; | 
| 104 | < | r2 = (dim[2]+urand(urind(ilhash(dim,4),i)))/nazi; | 
| 101 | > | h = ilhash(dim, 3) + i; | 
| 102 | > | multisamp(sp, 2, urand(h)); | 
| 103 | > | r1 = (dim[1] + sp[0])/nalt; | 
| 104 | > | r2 = (dim[2] + sp[1] - .5)/nazi; | 
| 105 |  | flatdir(dn, r1, r2); | 
| 106 |  | for (j = 0; j < 3; j++) | 
| 107 |  | dir[j] = -dn[0]*u[j] - dn[1]*v[j] - dn[2]*fa->norm[j]; | 
| 108 |  | /* random location */ | 
| 109 |  | do { | 
| 110 | < | dim[3] = 3; | 
| 111 | < | r1 = ur[0] + (ur[1]-ur[0]) * | 
| 112 | < | 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)); | 
| 110 | > | multisamp(sp, 2, urand(h+4862+nmisses)); | 
| 111 | > | r1 = ur[0] + (ur[1]-ur[0]) * sp[0]; | 
| 112 | > | r2 = vr[0] + (vr[1]-vr[0]) * sp[1]; | 
| 113 |  | for (j = 0; j < 3; j++) | 
| 114 |  | org[j] = r1*u[j] + r2*v[j] | 
| 115 |  | + fa->offset*fa->norm[j]; | 
| 125 |  | for (j = 0; j < 3; j++) | 
| 126 |  | org[j] += .001*fa->norm[j]; | 
| 127 |  | /* send sample */ | 
| 128 | < | raysamp(distarr+dim[1]*nazi+dim[2], org, dir, rt); | 
| 128 | > | raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt); | 
| 129 |  | } | 
| 130 |  | rayflush(rt); | 
| 131 | < | /* write out the face w/ distribution */ | 
| 132 | < | flatout(il, distarr, nalt, nazi, u, v, fa->norm); | 
| 133 | < | illumout(il, ob); | 
| 131 | > | /* write out the face and its distribution */ | 
| 132 | > | if (average(il, distarr, nalt*nazi)) { | 
| 133 | > | if (il->sampdens > 0) | 
| 134 | > | flatout(il, distarr, nalt, nazi, u, v, fa->norm); | 
| 135 | > | illumout(il, ob); | 
| 136 | > | } else | 
| 137 | > | printobj(il->altmat, ob); | 
| 138 |  | /* clean up */ | 
| 139 |  | freeface(ob); | 
| 140 |  | free((char *)distarr); | 
| 148 |  | struct rtproc  *rt; | 
| 149 |  | char  *nm; | 
| 150 |  | { | 
| 151 | < | int  dim[4]; | 
| 151 | > | int  dim[3]; | 
| 152 |  | int  n, nalt, nazi; | 
| 153 |  | float  *distarr; | 
| 154 | < | double  r1, r2, r3; | 
| 154 | > | double  sp[4], r1, r2, r3; | 
| 155 |  | FVECT  org, dir; | 
| 156 |  | FVECT  u, v; | 
| 157 |  | register int  i, j; | 
| 159 |  | if (ob->oargs.nfargs != 4) | 
| 160 |  | objerror(ob, USER, "bad # of arguments"); | 
| 161 |  | /* set up sampling */ | 
| 162 | < | n = 4.*PI * il->sampdens; | 
| 163 | < | nalt = sqrt(n/PI) + .5; | 
| 164 | < | nazi = PI*nalt + .5; | 
| 162 | > | if (il->sampdens <= 0) | 
| 163 | > | nalt = nazi = 1; | 
| 164 | > | else { | 
| 165 | > | n = 4.*PI * il->sampdens; | 
| 166 | > | nalt = sqrt(2./PI*n) + .5; | 
| 167 | > | nazi = PI/2.*nalt + .5; | 
| 168 | > | } | 
| 169 |  | n = nalt*nazi; | 
| 170 |  | distarr = (float *)calloc(n, 3*sizeof(float)); | 
| 171 |  | if (distarr == NULL) | 
| 173 |  | dim[0] = random(); | 
| 174 |  | /* sample sphere */ | 
| 175 |  | for (dim[1] = 0; dim[1] < nalt; dim[1]++) | 
| 176 | < | for (dim[2] = 0; dim[2] < nazi; dim[2]++) { | 
| 155 | < | if (il->nsamps > 2 && nazi > 20) { | 
| 156 | < | rounddir(dir, (dim[1]+.5)/nalt, (dim[2]+.5)/nazi); | 
| 157 | < | mkaxes(u, v, dir); | 
| 158 | < | } | 
| 176 | > | for (dim[2] = 0; dim[2] < nazi; dim[2]++) | 
| 177 |  | for (i = 0; i < il->nsamps; i++) { | 
| 178 | + | /* next sample point */ | 
| 179 | + | multisamp(sp, 4, urand(ilhash(dim,3)+i)); | 
| 180 |  | /* random direction */ | 
| 181 | < | dim[3] = 1; | 
| 182 | < | r1 = (dim[1]+urand(urind(ilhash(dim,4),i)))/nalt; | 
| 163 | < | dim[3] = 2; | 
| 164 | < | r2 = (dim[2]+urand(urind(ilhash(dim,4),i)))/nazi; | 
| 181 | > | r1 = (dim[1] + sp[0])/nalt; | 
| 182 | > | r2 = (dim[2] + sp[1] - .5)/nazi; | 
| 183 |  | rounddir(dir, r1, r2); | 
| 184 |  | /* random location */ | 
| 185 | < | if (il->nsamps <= 2 || nazi <= 20) | 
| 186 | < | mkaxes(u, v, dir);              /* yuck! */ | 
| 187 | < | dim[3] = 3; | 
| 170 | < | r3 = sqrt(urand(urind(ilhash(dim,4),i))); | 
| 171 | < | dim[3] = 4; | 
| 172 | < | r2 = 2.*PI*urand(urind(ilhash(dim,4),i)); | 
| 185 | > | mkaxes(u, v, dir);          /* yuck! */ | 
| 186 | > | r3 = sqrt(sp[2]); | 
| 187 | > | r2 = 2.*PI*sp[3]; | 
| 188 |  | r1 = r3*ob->oargs.farg[3]*cos(r2); | 
| 189 |  | r2 = r3*ob->oargs.farg[3]*sin(r2); | 
| 190 |  | r3 = ob->oargs.farg[3]*sqrt(1.01-r3*r3); | 
| 194 |  | dir[j] = -dir[j]; | 
| 195 |  | } | 
| 196 |  | /* send sample */ | 
| 197 | < | raysamp(distarr+dim[1]*nazi+dim[2], org, dir, rt); | 
| 197 | > | raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt); | 
| 198 |  | } | 
| 184 | – | } | 
| 199 |  | rayflush(rt); | 
| 200 | < | /* write out the sphere w/ distribution */ | 
| 201 | < | roundout(il, distarr, nalt, nazi); | 
| 202 | < | illumout(il, ob); | 
| 200 | > | /* write out the sphere and its distribution */ | 
| 201 | > | if (average(il, distarr, nalt*nazi)) { | 
| 202 | > | if (il->sampdens > 0) | 
| 203 | > | roundout(il, distarr, nalt, nazi); | 
| 204 | > | else | 
| 205 | > | objerror(ob, WARNING, "diffuse distribution"); | 
| 206 | > | illumout(il, ob); | 
| 207 | > | } else | 
| 208 | > | printobj(il->altmat, ob); | 
| 209 |  | /* clean up */ | 
| 210 |  | free((char *)distarr); | 
| 211 |  | } | 
| 217 |  | struct rtproc  *rt; | 
| 218 |  | char  *nm; | 
| 219 |  | { | 
| 220 | < | int  dim[4]; | 
| 220 | > | int  dim[3]; | 
| 221 |  | int  n, nalt, nazi; | 
| 222 |  | float  *distarr; | 
| 223 | < | double  r1, r2, r3; | 
| 223 | > | double  sp[4], r1, r2, r3; | 
| 224 |  | FVECT  dn, org, dir; | 
| 225 |  | FVECT  u, v; | 
| 226 |  | register CONE  *co; | 
| 228 |  | /* get/check arguments */ | 
| 229 |  | co = getcone(ob, 0); | 
| 230 |  | /* set up sampling */ | 
| 231 | < | n = PI * il->sampdens; | 
| 232 | < | nalt = sqrt(n/PI) + .5; | 
| 233 | < | nazi = PI*nalt + .5; | 
| 231 | > | if (il->sampdens <= 0) | 
| 232 | > | nalt = nazi = 1; | 
| 233 | > | else { | 
| 234 | > | n = PI * il->sampdens; | 
| 235 | > | nalt = sqrt(n/PI) + .5; | 
| 236 | > | nazi = PI*nalt + .5; | 
| 237 | > | } | 
| 238 |  | n = nalt*nazi; | 
| 239 |  | distarr = (float *)calloc(n, 3*sizeof(float)); | 
| 240 |  | if (distarr == NULL) | 
| 245 |  | for (dim[1] = 0; dim[1] < nalt; dim[1]++) | 
| 246 |  | for (dim[2] = 0; dim[2] < nazi; dim[2]++) | 
| 247 |  | for (i = 0; i < il->nsamps; i++) { | 
| 248 | + | /* next sample point */ | 
| 249 | + | multisamp(sp, 4, urand(ilhash(dim,3)+i)); | 
| 250 |  | /* random direction */ | 
| 251 | < | dim[3] = 1; | 
| 252 | < | r1 = (dim[1]+urand(urind(ilhash(dim,4),i)))/nalt; | 
| 227 | < | dim[3] = 2; | 
| 228 | < | r2 = (dim[2]+urand(urind(ilhash(dim,4),i)))/nalt; | 
| 251 | > | r1 = (dim[1] + sp[0])/nalt; | 
| 252 | > | r2 = (dim[2] + sp[1] - .5)/nazi; | 
| 253 |  | flatdir(dn, r1, r2); | 
| 254 |  | for (j = 0; j < 3; j++) | 
| 255 |  | dir[j] = -dn[0]*u[j] - dn[1]*v[j] - dn[2]*co->ad[j]; | 
| 256 |  | /* random location */ | 
| 233 | – | dim[3] = 3; | 
| 257 |  | r3 = sqrt(CO_R0(co)*CO_R0(co) + | 
| 258 | < | urand(urind(ilhash(dim,4),i))* | 
| 259 | < | (CO_R1(co)*CO_R1(co) - CO_R0(co)*CO_R0(co))); | 
| 237 | < | dim[3] = 4; | 
| 238 | < | r2 = 2.*PI*urand(urind(ilhash(dim,4),i)); | 
| 258 | > | sp[2]*(CO_R1(co)*CO_R1(co) - CO_R0(co)*CO_R0(co))); | 
| 259 | > | r2 = 2.*PI*sp[3]; | 
| 260 |  | r1 = r3*cos(r2); | 
| 261 |  | r2 = r3*sin(r2); | 
| 262 |  | for (j = 0; j < 3; j++) | 
| 263 | < | org[j] = CO_P0(co)[j] + r1*u[j] + r1*v[j] + | 
| 263 | > | org[j] = CO_P0(co)[j] + r1*u[j] + r2*v[j] + | 
| 264 |  | .001*co->ad[j]; | 
| 265 |  |  | 
| 266 |  | /* send sample */ | 
| 267 | < | raysamp(distarr+dim[1]*nazi+dim[2], org, dir, rt); | 
| 267 | > | raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt); | 
| 268 |  | } | 
| 269 |  | rayflush(rt); | 
| 270 | < | /* write out the ring w/ distribution */ | 
| 271 | < | flatout(il, distarr, nalt, nazi, u, v, co->ad); | 
| 272 | < | illumout(il, ob); | 
| 270 | > | /* write out the ring and its distribution */ | 
| 271 | > | if (average(il, distarr, nalt*nazi)) { | 
| 272 | > | if (il->sampdens > 0) | 
| 273 | > | flatout(il, distarr, nalt, nazi, u, v, co->ad); | 
| 274 | > | illumout(il, ob); | 
| 275 | > | } else | 
| 276 | > | printobj(il->altmat, ob); | 
| 277 |  | /* clean up */ | 
| 278 |  | freecone(ob); | 
| 279 |  | free((char *)distarr); | 
| 303 |  |  | 
| 304 |  | if (rt->nrays <= 0) | 
| 305 |  | return; | 
| 306 | < | i = 6*rt->nrays + 3; | 
| 307 | < | rt->buf[i++] = 0.; rt->buf[i++] = 0.; rt->buf[i] = 0.; | 
| 306 | > | bzero(rt->buf+6*rt->nrays, 6*sizeof(float)); | 
| 307 | > | errno = 0; | 
| 308 |  | if ( process(rt->pd, (char *)rt->buf, (char *)rt->buf, | 
| 309 | < | 3*sizeof(float)*rt->nrays, | 
| 309 | > | 3*sizeof(float)*(rt->nrays+1), | 
| 310 |  | 6*sizeof(float)*(rt->nrays+1)) < | 
| 311 | < | 3*sizeof(float)*rt->nrays ) | 
| 311 | > | 3*sizeof(float)*(rt->nrays+1) ) | 
| 312 |  | error(SYSTEM, "error reading from rtrace process"); | 
| 313 |  | i = rt->nrays; | 
| 314 |  | while (i--) { |