ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/virtuals.c
(Generate patch)

Comparing ray/src/rt/virtuals.c (file contents):
Revision 1.1 by greg, Wed Jun 19 16:36:14 1991 UTC vs.
Revision 1.3 by greg, Thu Jun 20 13:43:38 1991 UTC

# Line 11 | Line 11 | static char SCCSid[] = "$SunId$ LBL";
11  
12   #include  "ray.h"
13  
14 #include  "source.h"
15
14   #include  "otypes.h"
15  
16 + #include  "source.h"
17 +
18   #include  "cone.h"
19  
20   #include  "face.h"
21  
22 extern int  directrelay;                /* maximum number of source relays */
22  
24 double  getplaneq();
25 double  getmaxdisk();
23   double  intercircle();
24   SRCREC  *makevsrc();
25  
# Line 40 | Line 37 | markvirtuals()                 /* find and mark virtual sources */
37                                          /* find virtual source objects */
38          for (i = 0; i < nobjects; i++) {
39                  o = objptr(i);
40 <                if (o->omod == OVOID)
40 >                if (!issurface(o->otype) || o->omod == OVOID)
41                          continue;
42                  if (!isvlight(objptr(o->omod)->otype))
43                          continue;
44 +                if (sfun[o->otype].of == NULL ||
45 +                                sfun[o->otype].of->getpleq == NULL)
46 +                        objerror(o, USER, "illegal material");
47                  if (nvobjects == 0)
48                          vobject = (OBJECT *)malloc(sizeof(OBJECT));
49                  else
# Line 75 | Line 75 | int  nr;
75                  return;
76                                  /* check each virtual object for projection */
77          for (i = 0; i < nvobjects; i++)
78 <                vproject(objptr(i), sr, nr-1);  /* calls us recursively */
78 >                                        /* vproject() calls us recursively */
79 >                vproject(objptr(i), sr, nr-1);
80   }
81  
82  
83 + vproject(o, s, n)               /* create projected source(s) if they exist */
84 + OBJREC  *o;
85 + SRCREC  *s;
86 + int  n;
87 + {
88 +        register int  i;
89 +        register VSMATERIAL  *vsmat;
90 +        MAT4  proj;
91 +        SRCREC  *ns;
92 +                                /* get virtual source material */
93 +        vsmat = sfun[objptr(o->omod)->otype].mf;
94 +                                /* project virtual sources */
95 +        for (i = 0; i < vsmat->nproj; i++)
96 +                if ((*vsmat->vproj)(proj, o, s, i))
97 +                        if ((ns = makevsrc(o, s, proj)) != NULL)
98 +                                addvirtuals(ns, n);
99 + }
100 +
101 +
102   SRCREC *
103   makevsrc(op, sp, pm)            /* make virtual source if reasonable */
104   OBJREC  *op;
# Line 87 | Line 107 | MAT4  pm;
107   {
108          register SRCREC  *newsrc;
109          FVECT  nsloc, ocent, nsnorm;
110 +        int  nsflags;
111          double  maxrad2;
112 <        double  d1, d2;
112 >        double  d1;
113          SPOT  theirspot, ourspot;
114          register int  i;
115 +
116 +        nsflags = (sp->sflags|(SVIRTUAL|SFOLLOW)) & ~SSPOT;
117                                          /* get object center and max. radius */
118 <        maxrad2 = getmaxdisk(ocent, op);
119 <        if (maxrad2 <= FTINY)                   /* too small? */
120 <                return(NULL);
118 >        if (sfun[op->otype].of->getdisk != NULL) {
119 >                maxrad2 = (*sfun[op->otype].of->getdisk)(ocent, op);
120 >                if (maxrad2 <= FTINY)                   /* too small? */
121 >                        return(NULL);
122 >                nsflags |= SSPOT;
123 >        }
124                                          /* get location and spot */
125          if (sp->sflags & SDISTANT) {            /* distant source */
126                  if (sp->sflags & SPROX)
127                          return(NULL);           /* should never get here! */
128                  multv3(nsloc, sp->sloc, pm);
129 <                VCOPY(ourspot.aim, ocent);
130 <                ourspot.siz = PI*maxrad2;
131 <                ourspot.flen = 0.;
129 >                if (nsflags & SSPOT) {
130 >                        VCOPY(ourspot.aim, ocent);
131 >                        ourspot.siz = PI*maxrad2;
132 >                        ourspot.flen = 0.;
133 >                }
134                  if (sp->sflags & SSPOT) {
135                          copystruct(&theirspot, sp->sl.s);
136                          multp3(theirspot.aim, sp->sl.s->aim, pm);
137 <                        if (!commonbeam(&ourspot, &theirspot, nsloc))
137 >                        if (nsflags & SSPOT &&
138 >                                !commonbeam(&ourspot, &theirspot, nsloc))
139                                  return(NULL);           /* no overlap */
140                  }
141          } else {                                /* local source */
142                  multp3(nsloc, sp->sloc, pm);
143 <                if (sp->sflags & SPROX) {
144 <                        d2 = 0.;
145 <                        for (i = 0; i < 3; i++) {
146 <                                d1 = ocent[i] - nsloc[i];
147 <                                d2 += d1*d1;
148 <                        }
149 <                        if (d2 > sp->sl.prox*sp->sl.prox)
150 <                                return(NULL);   /* too far away */
143 >                if (nsflags & SSPOT) {
144 >                        for (i = 0; i < 3; i++)
145 >                                ourspot.aim[i] = ocent[i] - nsloc[i];
146 >                        if ((d1 = normalize(ourspot.aim)) == 0.)
147 >                                return(NULL);           /* at source!! */
148 >                        if (sp->sflags & SPROX && d1 > sp->sl.prox)
149 >                                return(NULL);           /* too far away */
150 >                        ourspot.siz = 2.*PI*(1. - d1/sqrt(d1*d1+maxrad2));
151 >                        ourspot.flen = 0.;
152 >                } else if (sp->sflags & SPROX) {
153 >                        FVECT  norm;
154 >                        double  offs;
155 >                                                /* use distance from plane */
156 >                        offs = (*sfun[op->otype].of->getpleq)(norm, op);
157 >                        d1 = DOT(norm, nsloc) - offs;
158 >                        if (d1 > sp->sl.prox || d1 < -sp->sl.prox)
159 >                                return(NULL);           /* too far away */
160                  }
123                for (i = 0; i < 3; i++)
124                        ourspot.aim[i] = ocent[i] - nsloc[i];
125                if ((d1 = normalize(ourspot.aim)) == 0.)
126                        return(NULL);           /* at source!! */
127                ourspot.siz = 2.*PI*(1. - d1/sqrt(d1*d1+maxrad2));
128                ourspot.flen = 0.;
161                  if (sp->sflags & SSPOT) {
162                          copystruct(&theirspot, sp->sl.s);
163                          multv3(theirspot.aim, sp->sl.s->aim, pm);
164 <                        if (!commonspot(&ourspot, &theirspot, nsloc))
165 <                                return(NULL);           /* no overlap */
166 <                        ourspot.flen = theirspot.flen;
164 >                        if (nsflags & SSPOT) {
165 >                                if (!commonspot(&ourspot, &theirspot, nsloc))
166 >                                        return(NULL);   /* no overlap */
167 >                                ourspot.flen = theirspot.flen;
168 >                        }
169                  }
170                  if (sp->sflags & SFLAT) {       /* check for behind source */
171                          multv3(nsnorm, sp->snorm, pm);
172 <                        if (checkspot(&ourspot, nsnorm) < 0)
172 >                        if (nsflags & SSPOT && checkspot(&ourspot, nsnorm) < 0)
173                                  return(NULL);
174                  }
175          }
176                                          /* everything is OK, make source */
177          if ((newsrc = newsource()) == NULL)
178                  goto memerr;
179 <        newsrc->sflags = sp->sflags | (SVIRTUAL|SSPOT|SFOLLOW);
179 >        newsrc->sflags = nsflags;
180          VCOPY(newsrc->sloc, nsloc);
181 <        if (newsrc->sflags & SFLAT)
181 >        if (nsflags & SFLAT)
182                  VCOPY(newsrc->snorm, nsnorm);
183          newsrc->ss = sp->ss; newsrc->ss2 = sp->ss2;
184 <        if ((newsrc->sl.s = (SPOT *)malloc(sizeof(SPOT))) == NULL)
185 <                goto memerr;
186 <        copystruct(newsrc->sl.s, &ourspot);
187 <        if (newsrc->sflags & SPROX)
184 >        if ((nsflags | sp->sflags) & SSPOT) {
185 >                if ((newsrc->sl.s = (SPOT *)malloc(sizeof(SPOT))) == NULL)
186 >                        goto memerr;
187 >                if (nsflags & SSPOT)
188 >                        copystruct(newsrc->sl.s, &ourspot);
189 >                else
190 >                        copystruct(newsrc->sl.s, &theirspot);
191 >                newsrc->sflags |= SSPOT;
192 >        }
193 >        if (nsflags & SPROX)
194                  newsrc->sl.prox = sp->sl.prox;
195          newsrc->sa.svnext = sp - source;
196          return(newsrc);
# Line 164 | Line 204 | register SPOT  *sp1, *sp2;
204   FVECT  org;
205   {
206          FVECT  cent;
207 <        double  rad2, d1r2, d2r2;
207 >        double  rad2, cos1, cos2;
208  
209 <        d1r2 = 1. - sp1->siz/(2.*PI);
210 <        d2r2 = 1. - sp2->siz/(2.*PI);
209 >        cos1 = 1. - sp1->siz/(2.*PI);
210 >        cos2 = 1. - sp2->siz/(2.*PI);
211          if (sp2->siz >= 2.*PI-FTINY)            /* BIG, just check overlap */
212 <                return(DOT(sp1->aim,sp2->aim) >= d1r2*d2r2 -
213 <                                        sqrt((1.-d1r2*d1r2)*(1.-d2r2*d2r2)));
212 >                return(DOT(sp1->aim,sp2->aim) >= cos1*cos2 -
213 >                                        sqrt((1.-cos1*cos1)*(1.-cos2*cos2)));
214                                  /* compute and check disks */
215 <        d1r2 = 1./(d1r2*d1r2) - 1.;
216 <        d2r2 = 1./(d2r2*d2r2) - 1.;
177 <        rad2 = intercircle(cent, sp1->aim, sp2->aim, d1r2, d2r2);
215 >        rad2 = intercircle(cent, sp1->aim, sp2->aim,
216 >                        1./(cos1*cos1) - 1.,  1./(cos2*cos2) - 1.);
217          if (rad2 <= FTINY || normalize(cent) == 0.)
218                  return(0);
219          VCOPY(sp1->aim, cent);
# Line 193 | Line 232 | FVECT  dir;
232                                          /* move centers to common plane */
233          d = DOT(sp1->aim, dir);
234          for (i = 0; i < 3; i++)
235 <                c1[i] = sp2->aim[i] - d*dir[i];
235 >                c1[i] = sp1->aim[i] - d*dir[i];
236          d = DOT(sp2->aim, dir);
237          for (i = 0; i < 3; i++)
238                  c2[i] = sp2->aim[i] - d*dir[i];
# Line 222 | Line 261 | FVECT  nrm;
261   }
262  
263  
225 mirrorproj(m, nv, offs)         /* get mirror projection for surface */
226 register MAT4  m;
227 FVECT  nv;
228 double  offs;
229 {
230        register int  i, j;
231                                        /* assign matrix */
232        setident4(m);
233        for (i = 0; i < 3; i++)
234                for (j = 0; j < 3; j++)
235                        m[i][j] -= 2.*nv[i]*nv[j];
236        for (j = 0; j < 3; j++)
237                m[3][j] = 2.*offs*nv[j];
238 }
239
240
264   double
265   intercircle(cc, c1, c2, r1s, r2s)       /* intersect two circles */
266   FVECT  cc;                      /* midpoint (return value) */
# Line 267 | Line 290 | double  r1s, r2s;              /* radii squared */
290                                          /* no overlap? */
291          if (a2 <= 0.)
292                  return(0.);
293 +                                        /* overlap, compute center */
294          l = sqrt((r1s - a2)/d2);
295          for (i = 0; i < 3; i++)
296                  cc[i] = c1[i] + l*disp[i];
297          return(a2);
274 }
275
276
277 /*
278 * The following routines depend on the supported OBJECTS:
279 */
280
281
282 double
283 getmaxdisk(ocent, op)           /* get object center and squared radius */
284 FVECT  ocent;
285 register OBJREC  *op;
286 {
287        double  maxrad2;
288
289        switch (op->otype) {
290        case OBJ_FACE:
291                {
292                        double  d1, d2;
293                        register int  i, j;
294                        register FACE  *f = getface(op);
295
296                        for (i = 0; i < 3; i++) {
297                                ocent[i] = 0.;
298                                for (j = 0; j < f->nv; j++)
299                                        ocent[i] += VERTEX(f,j)[i];
300                                ocent[i] /= (double)f->nv;
301                        }
302                        maxrad2 = 0.;
303                        for (j = 0; j < f->nv; j++) {
304                                d2 = 0.;
305                                for (i = 0; i < 3; i++) {
306                                        d1 = VERTEX(f,j)[i] - ocent[i];
307                                        d2 += d1*d1;
308                                }
309                                if (d2 > maxrad2)
310                                        maxrad2 = d2;
311                        }
312                }
313                return(maxrad2);
314        case OBJ_RING:
315                {
316                        register CONE  *co = getcone(op, 0);
317
318                        VCOPY(ocent, CO_P0(co));
319                        maxrad2 = CO_R1(co);
320                        maxrad2 *= maxrad2;
321                }
322                return(maxrad2);
323        }
324        objerror(op, USER, "illegal material");
325 }
326
327
328 double
329 getplaneq(nvec, op)                     /* get plane equation for object */
330 FVECT  nvec;
331 OBJREC  *op;
332 {
333        register FACE  *fo;
334        register CONE  *co;
335
336        switch (op->otype) {
337        case OBJ_FACE:
338                fo = getface(op);
339                VCOPY(nvec, fo->norm);
340                return(fo->offset);
341        case OBJ_RING:
342                co = getcone(op, 0);
343                VCOPY(nvec, co->ad);
344                return(DOT(nvec, CO_P0(co)));
345        }
346        objerror(op, USER, "illegal material");
347 }
348
349
350 /*
351 * The following routines depend on the supported MATERIALS:
352 */
353
354
355 vproject(o, s, n)               /* create projected source(s) if they exist */
356 OBJREC  *o;
357 SRCREC  *s;
358 int  n;
359 {
360        SRCREC  *ns;
361        FVECT  norm;
362        double  offset;
363        MAT4  proj;
364                                /* get surface normal and offset */
365        offset = getplaneq(norm, o);
366        switch (objptr(o->omod)->otype) {
367        case MAT_MIRROR:                        /* mirror source */
368                if (DOT(s->sloc, norm) <= (s->sflags & SDISTANT ?
369                                        FTINY : offset+FTINY))
370                        return;                 /* behind mirror */
371                mirrorproj(proj, norm, offset);
372                if ((ns = makevsrc(o, s, proj)) != NULL)
373                        addvirtuals(ns, n);
374                break;
375        }
376 }
377
378
379 vsrcrelay(rn, rv)               /* relay virtual source ray */
380 register RAY  *rn, *rv;
381 {
382        int  snext;
383        register int  i;
384                                        /* source we're aiming for here */
385        snext = source[rv->rsrc].sa.svnext;
386                                        /* compute relayed ray direction */
387        switch (objptr(rv->ro->omod)->otype) {
388        case MAT_MIRROR:                /* mirror: singular reflection */
389                rayorigin(rn, rv, REFLECTED, 1.);
390                                        /* ignore textures */
391                for (i = 0; i < 3; i++)
392                        rn->rdir[i] = rv->rdir[i] + 2.*rv->rod*rv->ron[i];
393                break;
394 #ifdef DEBUG
395        default:
396                error(CONSISTENCY, "inappropriate material in vsrcrelay");
397 #endif
398        }
399        rn->rsrc = snext;
400 }
401
402
403 m_mirror(m, r)                  /* shade mirrored ray */
404 register OBJREC  *m;
405 register RAY  *r;
406 {
407        COLOR  mcolor;
408        RAY  nr;
409        register int  i;
410
411        if (m->oargs.nfargs != 3 || m->oargs.nsargs > 1)
412                objerror(m, USER, "bad number of arguments");
413        if (r->rsrc >= 0) {                     /* aiming for somebody */
414                if (source[r->rsrc].so != r->ro)
415                        return;                         /* but not us */
416        } else if (m->oargs.nsargs > 0) {       /* else call substitute? */
417                rayshade(r, modifier(m->oargs.sarg[0]));
418                return;
419        }
420        if (r->rod < 0.)                        /* back is black */
421                return;
422                                        /* get modifiers */
423        raytexture(r, m->omod);
424                                        /* assign material color */
425        setcolor(mcolor, m->oargs.farg[0],
426                        m->oargs.farg[1],
427                        m->oargs.farg[2]);
428        multcolor(mcolor, r->pcol);
429                                        /* compute reflected ray */
430        if (r->rsrc >= 0)                       /* relayed light source */
431                vsrcrelay(&nr, r);
432        else {                                  /* ordinary reflection */
433                FVECT  pnorm;
434                double  pdot;
435
436                if (rayorigin(&nr, r, REFLECTED, bright(mcolor)) < 0)
437                        return;
438                pdot = raynormal(pnorm, r);     /* use textures */
439                for (i = 0; i < 3; i++)
440                        nr.rdir[i] = r->rdir[i] + 2.*pdot*pnorm[i];
441        }
442        rayvalue(&nr);
443        multcolor(nr.rcol, mcolor);
444        addcolor(r->rcol, nr.rcol);
298   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines