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.2 by greg, Thu Jun 20 09:37:38 1991 UTC vs.
Revision 1.4 by greg, Thu Jun 20 16:36:48 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[sn], 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(NULL);
127 >                nsflags |= SSPOT;
128 >        }
129                                          /* get location and spot */
130 <        if (sp->sflags & SDISTANT) {            /* distant source */
131 <                if (sp->sflags & SPROX)
130 >        if (source[sn].sflags & SDISTANT) {             /* distant source */
131 >                if (source[sn].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) {
138 <                        copystruct(&theirspot, sp->sl.s);
139 <                        multp3(theirspot.aim, sp->sl.s->aim, pm);
140 <                        if (!commonbeam(&ourspot, &theirspot, nsloc))
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(NULL);           /* no overlap */
145                  }
146          } else {                                /* local source */
147 <                multp3(nsloc, sp->sloc, pm);
148 <                for (i = 0; i < 3; i++)
149 <                        ourspot.aim[i] = ocent[i] - nsloc[i];
150 <                if ((d1 = normalize(ourspot.aim)) == 0.)
151 <                        return(NULL);           /* at source!! */
152 <                if (sp->sflags & SPROX && d1 > sp->sl.prox)
153 <                        return(NULL);           /* too far away */
154 <                ourspot.siz = 2.*PI*(1. - d1/sqrt(d1*d1+maxrad2));
155 <                ourspot.flen = 0.;
156 <                if (sp->sflags & SSPOT) {
157 <                        copystruct(&theirspot, sp->sl.s);
158 <                        multv3(theirspot.aim, sp->sl.s->aim, pm);
159 <                        if (!commonspot(&ourspot, &theirspot, nsloc))
160 <                                return(NULL);           /* no overlap */
161 <                        ourspot.flen = theirspot.flen;
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(NULL);           /* at source!! */
153 >                        if (source[sn].sflags & SPROX &&
154 >                                        d1 > source[sn].sl.prox)
155 >                                return(NULL);           /* 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(NULL);           /* too far away */
167                  }
168 <                if (sp->sflags & SFLAT) {       /* check for behind source */
169 <                        multv3(nsnorm, sp->snorm, pm);
170 <                        if (checkspot(&ourspot, nsnorm) < 0)
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(NULL);   /* no overlap */
174 >                                ourspot.flen = theirspot.flen;
175 >                        }
176 >                }
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(NULL);
181                  }
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 214 | Line 269 | FVECT  nrm;
269   }
270  
271  
217 mirrorproj(m, nv, offs)         /* get mirror projection for surface */
218 register MAT4  m;
219 FVECT  nv;
220 double  offs;
221 {
222        register int  i, j;
223                                        /* assign matrix */
224        setident4(m);
225        for (i = 0; i < 3; i++)
226                for (j = 0; j < 3; j++)
227                        m[i][j] -= 2.*nv[i]*nv[j];
228        for (j = 0; j < 3; j++)
229                m[3][j] = 2.*offs*nv[j];
230 }
231
232
272   double
273   intercircle(cc, c1, c2, r1s, r2s)       /* intersect two circles */
274   FVECT  cc;                      /* midpoint (return value) */
# Line 267 | Line 306 | double  r1s, r2s;              /* radii squared */
306   }
307  
308  
270 /*
271 * The following routines depend on the supported OBJECTS:
272 */
273
274
275 double
276 getmaxdisk(ocent, op)           /* get object center and squared radius */
277 FVECT  ocent;
278 register OBJREC  *op;
279 {
280        double  maxrad2;
281
282        switch (op->otype) {
283        case OBJ_FACE:
284                {
285                        double  d2;
286                        register int  i, j;
287                        register FACE  *f = getface(op);
288
289                        for (i = 0; i < 3; i++) {
290                                ocent[i] = 0.;
291                                for (j = 0; j < f->nv; j++)
292                                        ocent[i] += VERTEX(f,j)[i];
293                                ocent[i] /= (double)f->nv;
294                        }
295                        maxrad2 = 0.;
296                        for (j = 0; j < f->nv; j++) {
297                                d2 = dist2(VERTEX(f,j), ocent);
298                                if (d2 > maxrad2)
299                                        maxrad2 = d2;
300                        }
301                }
302                return(maxrad2);
303        case OBJ_RING:
304                {
305                        register CONE  *co = getcone(op, 0);
306
307                        VCOPY(ocent, CO_P0(co));
308                        maxrad2 = CO_R1(co);
309                        maxrad2 *= maxrad2;
310                }
311                return(maxrad2);
312        }
313        objerror(op, USER, "illegal material");
314 }
315
316
317 double
318 getplaneq(nvec, op)                     /* get plane equation for object */
319 FVECT  nvec;
320 OBJREC  *op;
321 {
322        register FACE  *fo;
323        register CONE  *co;
324
325        switch (op->otype) {
326        case OBJ_FACE:
327                fo = getface(op);
328                VCOPY(nvec, fo->norm);
329                return(fo->offset);
330        case OBJ_RING:
331                co = getcone(op, 0);
332                VCOPY(nvec, co->ad);
333                return(DOT(nvec, CO_P0(co)));
334        }
335        objerror(op, USER, "illegal material");
336 }
337
338
339 /*
340 * The following routines depend on the supported MATERIALS:
341 */
342
343
344 vproject(o, s, n)               /* create projected source(s) if they exist */
345 OBJREC  *o;
346 SRCREC  *s;
347 int  n;
348 {
349        SRCREC  *ns;
350        FVECT  norm;
351        double  offset;
352        MAT4  proj;
353                                /* get surface normal and offset */
354        offset = getplaneq(norm, o);
355        switch (objptr(o->omod)->otype) {
356        case MAT_MIRROR:                        /* mirror source */
357                if (DOT(s->sloc, norm) <= (s->sflags & SDISTANT ?
358                                        FTINY : offset+FTINY))
359                        return;                 /* behind mirror */
360                mirrorproj(proj, norm, offset);
361                if ((ns = makevsrc(o, s, proj)) != NULL)
362                        addvirtuals(ns, n);
363                break;
364        }
365 }
366
367
368 vsrcrelay(rn, rv)               /* relay virtual source ray */
369 register RAY  *rn, *rv;
370 {
371        int  snext;
372        register int  i;
373                                        /* source we're aiming for here */
374        snext = source[rv->rsrc].sa.svnext;
375                                        /* compute relayed ray direction */
376        switch (objptr(rv->ro->omod)->otype) {
377        case MAT_MIRROR:                /* mirror: singular reflection */
378                rayorigin(rn, rv, REFLECTED, 1.);
379                                        /* ignore textures */
380                for (i = 0; i < 3; i++)
381                        rn->rdir[i] = rv->rdir[i] + 2.*rv->rod*rv->ron[i];
382                break;
309   #ifdef DEBUG
310 <        default:
311 <                error(CONSISTENCY, "inappropriate material in vsrcrelay");
312 < #endif
387 <        }
388 <        rn->rsrc = snext;
389 < }
390 <
391 <
392 < m_mirror(m, r)                  /* shade mirrored ray */
393 < register OBJREC  *m;
394 < register RAY  *r;
310 > virtverb(vs, fp)        /* print verbose description of virtual source */
311 > register SRCREC  *vs;
312 > FILE  *fp;
313   {
396        COLOR  mcolor;
397        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;
411 <                                        /* get modifiers */
412 <        raytexture(r, m->omod);
413 <                                        /* assign material color */
414 <        setcolor(mcolor, m->oargs.farg[0],
415 <                        m->oargs.farg[1],
416 <                        m->oargs.farg[2]);
417 <        multcolor(mcolor, r->pcol);
418 <                                        /* compute reflected ray */
419 <        if (r->rsrc >= 0)                       /* relayed light source */
420 <                vsrcrelay(&nr, r);
421 <        else {                                  /* ordinary reflection */
422 <                FVECT  pnorm;
423 <                double  pdot;
424 <
425 <                if (rayorigin(&nr, r, REFLECTED, bright(mcolor)) < 0)
426 <                        return;
427 <                pdot = raynormal(pnorm, r);     /* use textures */
428 <                for (i = 0; i < 3; i++)
429 <                        nr.rdir[i] = r->rdir[i] + 2.*pdot*pnorm[i];
430 <        }
431 <        rayvalue(&nr);
432 <        multcolor(nr.rcol, mcolor);
433 <        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