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.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 <                for (i = 0; i < 3; i++)
144 <                        ourspot.aim[i] = ocent[i] - nsloc[i];
145 <                if ((d1 = normalize(ourspot.aim)) == 0.)
146 <                        return(NULL);           /* at source!! */
147 <                if (sp->sflags & SPROX && d1 > sp->sl.prox)
148 <                        return(NULL);           /* too far away */
149 <                ourspot.siz = 2.*PI*(1. - d1/sqrt(d1*d1+maxrad2));
150 <                ourspot.flen = 0.;
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 >                }
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 214 | Line 261 | FVECT  nrm;
261   }
262  
263  
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
264   double
265   intercircle(cc, c1, c2, r1s, r2s)       /* intersect two circles */
266   FVECT  cc;                      /* midpoint (return value) */
# Line 264 | Line 295 | double  r1s, r2s;              /* radii squared */
295          for (i = 0; i < 3; i++)
296                  cc[i] = c1[i] + l*disp[i];
297          return(a2);
267 }
268
269
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;
383 #ifdef DEBUG
384        default:
385                error(CONSISTENCY, "inappropriate material in vsrcrelay");
386 #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;
395 {
396        COLOR  mcolor;
397        RAY  nr;
398        register int  i;
399
400        if (m->oargs.nfargs != 3 || m->oargs.nsargs > 1)
401                objerror(m, USER, "bad number of arguments");
402        if (r->rsrc >= 0) {                     /* aiming for somebody */
403                if (source[r->rsrc].so != r->ro)
404                        return;                         /* but not us */
405        } else if (m->oargs.nsargs > 0) {       /* else call substitute? */
406                rayshade(r, modifier(m->oargs.sarg[0]));
407                return;
408        }
409        if (r->rod < 0.)                        /* back is black */
410                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);
298   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines