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.5 by greg, Thu Jun 20 17:08:39 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  "cone.h"
16 > #include  "source.h"
17  
20 #include  "face.h"
18  
22 extern int  directrelay;                /* maximum number of source relays */
23
24 double  getplaneq();
25 double  getmaxdisk();
19   double  intercircle();
27 SRCREC  *makevsrc();
20  
21   static OBJECT  *vobject;                /* virtual source objects */
22   static int  nvobjects = 0;              /* number of virtual source objects */
# Line 40 | Line 32 | markvirtuals()                 /* find and mark virtual sources */
32                                          /* find virtual source objects */
33          for (i = 0; i < nobjects; i++) {
34                  o = objptr(i);
35 <                if (o->omod == OVOID)
35 >                if (!issurface(o->otype) || o->omod == OVOID)
36                          continue;
37                  if (!isvlight(objptr(o->omod)->otype))
38                          continue;
39 +                if (sfun[o->otype].of == NULL ||
40 +                                sfun[o->otype].of->getpleq == NULL)
41 +                        objerror(o, USER, "illegal material");
42                  if (nvobjects == 0)
43                          vobject = (OBJECT *)malloc(sizeof(OBJECT));
44                  else
# Line 55 | Line 50 | markvirtuals()                 /* find and mark virtual sources */
50          }
51          if (nvobjects == 0)
52                  return;
53 + #ifdef DEBUG
54 +        fprintf(stderr, "found %d virtual source objects\n", nvobjects);
55 + #endif
56                                          /* append virtual sources */
57          for (i = nsources; i-- > 0; )
58                  if (!(source[i].sflags & SSKIP))
59 <                        addvirtuals(&source[i], directrelay);
59 >                        addvirtuals(i, directrelay);
60                                          /* done with our object list */
61          free((char *)vobject);
62          nvobjects = 0;
63   }
64  
65  
66 < addvirtuals(sr, nr)             /* add virtual sources associated with sr */
67 < SRCREC  *sr;
66 > addvirtuals(sn, nr)             /* add virtuals associated with source */
67 > int  sn;
68   int  nr;
69   {
70          register int  i;
# Line 75 | Line 73 | int  nr;
73                  return;
74                                  /* check each virtual object for projection */
75          for (i = 0; i < nvobjects; i++)
76 <                vproject(objptr(i), sr, nr-1);  /* calls us recursively */
76 >                                        /* vproject() calls us recursively */
77 >                vproject(objptr(vobject[i]), sn, nr-1);
78   }
79  
80  
81 < SRCREC *
82 < makevsrc(op, sp, pm)            /* make virtual source if reasonable */
81 > vproject(o, sn, n)              /* create projected source(s) if they exist */
82 > OBJREC  *o;
83 > int  sn;
84 > int  n;
85 > {
86 >        register int  i;
87 >        register VSMATERIAL  *vsmat;
88 >        MAT4  proj;
89 >        int  ns;
90 >
91 >        if (o == source[sn].so) /* objects cannot project themselves */
92 >                return;
93 >                                /* get virtual source material */
94 >        vsmat = sfun[objptr(o->omod)->otype].mf;
95 >                                /* project virtual sources */
96 >        for (i = 0; i < vsmat->nproj; i++)
97 >                if ((*vsmat->vproj)(proj, o, &source[sn], i))
98 >                        if ((ns = makevsrc(o, sn, proj)) >= 0) {
99 > #ifdef DEBUG
100 >                                virtverb(&source[ns], stderr);
101 > #endif
102 >                                addvirtuals(ns, n);
103 >                        }
104 > }
105 >
106 >
107 > int
108 > makevsrc(op, sn, pm)            /* make virtual source if reasonable */
109   OBJREC  *op;
110 < register SRCREC  *sp;
110 > register int  sn;
111   MAT4  pm;
112   {
113 <        register SRCREC  *newsrc;
113 >        register int  nsn;
114          FVECT  nsloc, ocent, nsnorm;
115 +        int  nsflags;
116          double  maxrad2;
117 <        double  d1, d2;
117 >        double  d1;
118          SPOT  theirspot, ourspot;
119          register int  i;
120 +
121 +        nsflags = (source[sn].sflags|(SVIRTUAL|SFOLLOW)) & ~SSPOT;
122                                          /* get object center and max. radius */
123 <        maxrad2 = getmaxdisk(ocent, op);
124 <        if (maxrad2 <= FTINY)                   /* too small? */
125 <                return(NULL);
123 >        if (sfun[op->otype].of->getdisk != NULL) {
124 >                maxrad2 = (*sfun[op->otype].of->getdisk)(ocent, op);
125 >                if (maxrad2 <= FTINY)                   /* too small? */
126 >                        return(-1);
127 >                nsflags |= SSPOT;
128 >        }
129                                          /* get location and spot */
130 <        if (sp->sflags & SDISTANT) {            /* distant source */
131 <                if (sp->sflags & SPROX)
132 <                        return(NULL);           /* should never get here! */
133 <                multv3(nsloc, sp->sloc, pm);
134 <                VCOPY(ourspot.aim, ocent);
135 <                ourspot.siz = PI*maxrad2;
136 <                ourspot.flen = 0.;
137 <                if (sp->sflags & SSPOT) {
107 <                        copystruct(&theirspot, sp->sl.s);
108 <                        multp3(theirspot.aim, sp->sl.s->aim, pm);
109 <                        if (!commonbeam(&ourspot, &theirspot, nsloc))
110 <                                return(NULL);           /* no overlap */
130 >        if (source[sn].sflags & SDISTANT) {             /* distant source */
131 >                if (source[sn].sflags & SPROX)
132 >                        return(-1);             /* should never get here! */
133 >                multv3(nsloc, source[sn].sloc, pm);
134 >                if (nsflags & SSPOT) {
135 >                        VCOPY(ourspot.aim, ocent);
136 >                        ourspot.siz = PI*maxrad2;
137 >                        ourspot.flen = 0.;
138                  }
139 +                if (source[sn].sflags & SSPOT) {
140 +                        copystruct(&theirspot, source[sn].sl.s);
141 +                        multp3(theirspot.aim, source[sn].sl.s->aim, pm);
142 +                        if (nsflags & SSPOT &&
143 +                                !commonbeam(&ourspot, &theirspot, nsloc))
144 +                                return(-1);             /* no overlap */
145 +                }
146          } else {                                /* local source */
147 <                multp3(nsloc, sp->sloc, pm);
148 <                if (sp->sflags & SPROX) {
149 <                        d2 = 0.;
150 <                        for (i = 0; i < 3; i++) {
151 <                                d1 = ocent[i] - nsloc[i];
152 <                                d2 += d1*d1;
147 >                multp3(nsloc, source[sn].sloc, pm);
148 >                if (nsflags & SSPOT) {
149 >                        for (i = 0; i < 3; i++)
150 >                                ourspot.aim[i] = ocent[i] - nsloc[i];
151 >                        if ((d1 = normalize(ourspot.aim)) == 0.)
152 >                                return(-1);             /* at source!! */
153 >                        if (source[sn].sflags & SPROX &&
154 >                                        d1 > source[sn].sl.prox)
155 >                                return(-1);             /* too far away */
156 >                        ourspot.siz = 2.*PI*(1. - d1/sqrt(d1*d1+maxrad2));
157 >                        ourspot.flen = 0.;
158 >                } else if (source[sn].sflags & SPROX) {
159 >                        FVECT  norm;
160 >                        double  offs;
161 >                                                /* use distance from plane */
162 >                        offs = (*sfun[op->otype].of->getpleq)(norm, op);
163 >                        d1 = DOT(norm, nsloc) - offs;
164 >                        if (d1 < 0.) d1 = -d1;
165 >                        if (d1 > source[sn].sl.prox)
166 >                                return(-1);             /* too far away */
167 >                }
168 >                if (source[sn].sflags & SSPOT) {
169 >                        copystruct(&theirspot, source[sn].sl.s);
170 >                        multv3(theirspot.aim, source[sn].sl.s->aim, pm);
171 >                        if (nsflags & SSPOT) {
172 >                                if (!commonspot(&ourspot, &theirspot, nsloc))
173 >                                        return(-1);     /* no overlap */
174 >                                ourspot.flen = theirspot.flen;
175                          }
120                        if (d2 > sp->sl.prox*sp->sl.prox)
121                                return(NULL);   /* too far away */
176                  }
177 <                for (i = 0; i < 3; i++)
178 <                        ourspot.aim[i] = ocent[i] - nsloc[i];
179 <                if ((d1 = normalize(ourspot.aim)) == 0.)
180 <                        return(NULL);           /* at source!! */
127 <                ourspot.siz = 2.*PI*(1. - d1/sqrt(d1*d1+maxrad2));
128 <                ourspot.flen = 0.;
129 <                if (sp->sflags & SSPOT) {
130 <                        copystruct(&theirspot, sp->sl.s);
131 <                        multv3(theirspot.aim, sp->sl.s->aim, pm);
132 <                        if (!commonspot(&ourspot, &theirspot, nsloc))
133 <                                return(NULL);           /* no overlap */
134 <                        ourspot.flen = theirspot.flen;
177 >                if (source[sn].sflags & SFLAT) {        /* behind source? */
178 >                        multv3(nsnorm, source[sn].snorm, pm);
179 >                        if (nsflags & SSPOT && checkspot(&ourspot, nsnorm) < 0)
180 >                                return(-1);
181                  }
136                if (sp->sflags & SFLAT) {       /* check for behind source */
137                        multv3(nsnorm, sp->snorm, pm);
138                        if (checkspot(&ourspot, nsnorm) < 0)
139                                return(NULL);
140                }
182          }
183                                          /* everything is OK, make source */
184 <        if ((newsrc = newsource()) == NULL)
184 >        if ((nsn = newsource()) < 0)
185                  goto memerr;
186 <        newsrc->sflags = sp->sflags | (SVIRTUAL|SSPOT|SFOLLOW);
187 <        VCOPY(newsrc->sloc, nsloc);
188 <        if (newsrc->sflags & SFLAT)
189 <                VCOPY(newsrc->snorm, nsnorm);
190 <        newsrc->ss = sp->ss; newsrc->ss2 = sp->ss2;
191 <        if ((newsrc->sl.s = (SPOT *)malloc(sizeof(SPOT))) == NULL)
192 <                goto memerr;
193 <        copystruct(newsrc->sl.s, &ourspot);
194 <        if (newsrc->sflags & SPROX)
195 <                newsrc->sl.prox = sp->sl.prox;
196 <        newsrc->sa.svnext = sp - source;
197 <        return(newsrc);
186 >        source[nsn].sflags = nsflags;
187 >        VCOPY(source[nsn].sloc, nsloc);
188 >        if (nsflags & SFLAT)
189 >                VCOPY(source[nsn].snorm, nsnorm);
190 >        source[nsn].ss = source[sn].ss; source[nsn].ss2 = source[sn].ss2;
191 >        if ((nsflags | source[sn].sflags) & SSPOT) {
192 >                if ((source[nsn].sl.s = (SPOT *)malloc(sizeof(SPOT))) == NULL)
193 >                        goto memerr;
194 >                if (nsflags & SSPOT)
195 >                        copystruct(source[nsn].sl.s, &ourspot);
196 >                else
197 >                        copystruct(source[nsn].sl.s, &theirspot);
198 >                source[nsn].sflags |= SSPOT;
199 >        }
200 >        if (nsflags & SPROX)
201 >                source[nsn].sl.prox = source[sn].sl.prox;
202 >        source[nsn].sa.svnext = sn;
203 >        source[nsn].so = op;
204 >        return(nsn);
205   memerr:
206          error(SYSTEM, "out of memory in makevsrc");
207   }
# Line 164 | Line 212 | register SPOT  *sp1, *sp2;
212   FVECT  org;
213   {
214          FVECT  cent;
215 <        double  rad2, d1r2, d2r2;
215 >        double  rad2, cos1, cos2;
216  
217 <        d1r2 = 1. - sp1->siz/(2.*PI);
218 <        d2r2 = 1. - sp2->siz/(2.*PI);
217 >        cos1 = 1. - sp1->siz/(2.*PI);
218 >        cos2 = 1. - sp2->siz/(2.*PI);
219          if (sp2->siz >= 2.*PI-FTINY)            /* BIG, just check overlap */
220 <                return(DOT(sp1->aim,sp2->aim) >= d1r2*d2r2 -
221 <                                        sqrt((1.-d1r2*d1r2)*(1.-d2r2*d2r2)));
220 >                return(DOT(sp1->aim,sp2->aim) >= cos1*cos2 -
221 >                                        sqrt((1.-cos1*cos1)*(1.-cos2*cos2)));
222                                  /* compute and check disks */
223 <        d1r2 = 1./(d1r2*d1r2) - 1.;
224 <        d2r2 = 1./(d2r2*d2r2) - 1.;
177 <        rad2 = intercircle(cent, sp1->aim, sp2->aim, d1r2, d2r2);
223 >        rad2 = intercircle(cent, sp1->aim, sp2->aim,
224 >                        1./(cos1*cos1) - 1.,  1./(cos2*cos2) - 1.);
225          if (rad2 <= FTINY || normalize(cent) == 0.)
226                  return(0);
227          VCOPY(sp1->aim, cent);
# Line 193 | Line 240 | FVECT  dir;
240                                          /* move centers to common plane */
241          d = DOT(sp1->aim, dir);
242          for (i = 0; i < 3; i++)
243 <                c1[i] = sp2->aim[i] - d*dir[i];
243 >                c1[i] = sp1->aim[i] - d*dir[i];
244          d = DOT(sp2->aim, dir);
245          for (i = 0; i < 3; i++)
246                  c2[i] = sp2->aim[i] - d*dir[i];
# Line 222 | Line 269 | FVECT  nrm;
269   }
270  
271  
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
272   double
273   intercircle(cc, c1, c2, r1s, r2s)       /* intersect two circles */
274   FVECT  cc;                      /* midpoint (return value) */
# Line 267 | Line 298 | double  r1s, r2s;              /* radii squared */
298                                          /* no overlap? */
299          if (a2 <= 0.)
300                  return(0.);
301 +                                        /* overlap, compute center */
302          l = sqrt((r1s - a2)/d2);
303          for (i = 0; i < 3; i++)
304                  cc[i] = c1[i] + l*disp[i];
# Line 274 | Line 306 | double  r1s, r2s;              /* radii squared */
306   }
307  
308  
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;
309   #ifdef DEBUG
310 <        default:
311 <                error(CONSISTENCY, "inappropriate material in vsrcrelay");
312 < #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;
310 > virtverb(vs, fp)        /* print verbose description of virtual source */
311 > register SRCREC  *vs;
312 > FILE  *fp;
313   {
407        COLOR  mcolor;
408        RAY  nr;
314          register int  i;
315  
316 <        if (m->oargs.nfargs != 3 || m->oargs.nsargs > 1)
317 <                objerror(m, USER, "bad number of arguments");
318 <        if (r->rsrc >= 0) {                     /* aiming for somebody */
319 <                if (source[r->rsrc].so != r->ro)
320 <                        return;                         /* but not us */
321 <        } else if (m->oargs.nsargs > 0) {       /* else call substitute? */
322 <                rayshade(r, modifier(m->oargs.sarg[0]));
316 >        fprintf(fp, "%s virtual source %d in %s %s\n",
317 >                        vs->sflags & SDISTANT ? "distant" : "local",
318 >                        vs-source, ofun[vs->so->otype].funame, vs->so->oname);
319 >        fprintf(fp, "\tat (%f,%f,%f)\n",
320 >                        vs->sloc[0], vs->sloc[1], vs->sloc[2]);
321 >        fprintf(fp, "\tlinked to source %d (%s)\n",
322 >                        vs->sa.svnext, source[vs->sa.svnext].so->oname);
323 >        if (vs->sflags & SFOLLOW)
324 >                fprintf(fp, "\talways followed\n");
325 >        else
326 >                fprintf(fp, "\tnever followed\n");
327 >        if (!(vs->sflags & SSPOT))
328                  return;
329 <        }
330 <        if (r->rod < 0.)                        /* back is black */
331 <                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);
329 >        fprintf(fp, "\twith spot aim (%f,%f,%f) and size %f\n",
330 >                        vs->sl.s->aim[0], vs->sl.s->aim[1], vs->sl.s->aim[2],
331 >                        vs->sl.s->siz);
332   }
333 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines