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.6 by greg, Fri Jun 21 13:25:42 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  
19 < extern int  directrelay;                /* maximum number of source relays */
19 > double  intercircle(), getdisk();
20  
24 double  getplaneq();
25 double  getmaxdisk();
26 double  intercircle();
27 SRCREC  *makevsrc();
28
21   static OBJECT  *vobject;                /* virtual source objects */
22   static int  nvobjects = 0;              /* number of virtual source objects */
23  
# 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(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;
89 <        FVECT  nsloc, ocent, nsnorm;
113 >        FVECT  nsloc, nsnorm, ocent;
114          double  maxrad2;
115 <        double  d1, d2;
115 >        int  nsflags;
116 >        double  d1;
117          SPOT  theirspot, ourspot;
118          register int  i;
119 +
120 +        nsflags = source[sn].sflags | (SVIRTUAL|SSPOT|SFOLLOW);
121                                          /* get object center and max. radius */
122 <        maxrad2 = getmaxdisk(ocent, op);
122 >        maxrad2 = getdisk(ocent, op, sn);
123          if (maxrad2 <= FTINY)                   /* too small? */
124 <                return(NULL);
124 >                return(-1);
125                                          /* get location and spot */
126 <        if (sp->sflags & SDISTANT) {            /* distant source */
127 <                if (sp->sflags & SPROX)
128 <                        return(NULL);           /* should never get here! */
129 <                multv3(nsloc, sp->sloc, pm);
126 >        if (source[sn].sflags & SDISTANT) {             /* distant source */
127 >                if (source[sn].sflags & SPROX)
128 >                        return(-1);             /* should never get here! */
129 >                multv3(nsloc, source[sn].sloc, pm);
130                  VCOPY(ourspot.aim, ocent);
131                  ourspot.siz = PI*maxrad2;
132                  ourspot.flen = 0.;
133 <                if (sp->sflags & SSPOT) {
134 <                        copystruct(&theirspot, sp->sl.s);
135 <                        multp3(theirspot.aim, sp->sl.s->aim, pm);
133 >                if (source[sn].sflags & SSPOT) {
134 >                        copystruct(&theirspot, source[sn].sl.s);
135 >                        multp3(theirspot.aim, source[sn].sl.s->aim, pm);
136                          if (!commonbeam(&ourspot, &theirspot, nsloc))
137 <                                return(NULL);           /* no overlap */
137 >                                return(-1);             /* no overlap */
138                  }
139          } else {                                /* local source */
140 <                multp3(nsloc, sp->sloc, pm);
140 >                multp3(nsloc, source[sn].sloc, pm);
141                  for (i = 0; i < 3; i++)
142                          ourspot.aim[i] = ocent[i] - nsloc[i];
143                  if ((d1 = normalize(ourspot.aim)) == 0.)
144 <                        return(NULL);           /* at source!! */
145 <                if (sp->sflags & SPROX && d1 > sp->sl.prox)
146 <                        return(NULL);           /* too far away */
144 >                        return(-1);             /* at source!! */
145 >                if (source[sn].sflags & SPROX && d1 > source[sn].sl.prox)
146 >                        return(-1);             /* too far away */
147                  ourspot.siz = 2.*PI*(1. - d1/sqrt(d1*d1+maxrad2));
148                  ourspot.flen = 0.;
149 <                if (sp->sflags & SSPOT) {
150 <                        copystruct(&theirspot, sp->sl.s);
151 <                        multv3(theirspot.aim, sp->sl.s->aim, pm);
149 >                if (source[sn].sflags & SSPOT) {
150 >                        copystruct(&theirspot, source[sn].sl.s);
151 >                        multv3(theirspot.aim, source[sn].sl.s->aim, pm);
152                          if (!commonspot(&ourspot, &theirspot, nsloc))
153 <                                return(NULL);           /* no overlap */
153 >                                return(-1);     /* no overlap */
154                          ourspot.flen = theirspot.flen;
155                  }
156 <                if (sp->sflags & SFLAT) {       /* check for behind source */
157 <                        multv3(nsnorm, sp->snorm, pm);
156 >                if (source[sn].sflags & SFLAT) {        /* behind source? */
157 >                        multv3(nsnorm, source[sn].snorm, pm);
158                          if (checkspot(&ourspot, nsnorm) < 0)
159 <                                return(NULL);
159 >                                return(-1);
160                  }
161          }
162                                          /* everything is OK, make source */
163 <        if ((newsrc = newsource()) == NULL)
163 >        if ((i = newsource()) < 0)
164                  goto memerr;
165 <        newsrc->sflags = sp->sflags | (SVIRTUAL|SSPOT|SFOLLOW);
166 <        VCOPY(newsrc->sloc, nsloc);
167 <        if (newsrc->sflags & SFLAT)
168 <                VCOPY(newsrc->snorm, nsnorm);
169 <        newsrc->ss = sp->ss; newsrc->ss2 = sp->ss2;
170 <        if ((newsrc->sl.s = (SPOT *)malloc(sizeof(SPOT))) == NULL)
165 >        source[i].sflags = nsflags;
166 >        VCOPY(source[i].sloc, nsloc);
167 >        if (nsflags & SFLAT)
168 >                VCOPY(source[i].snorm, nsnorm);
169 >        source[i].ss = source[sn].ss; source[i].ss2 = source[sn].ss2;
170 >        if ((source[i].sl.s = (SPOT *)malloc(sizeof(SPOT))) == NULL)
171                  goto memerr;
172 <        copystruct(newsrc->sl.s, &ourspot);
173 <        if (newsrc->sflags & SPROX)
174 <                newsrc->sl.prox = sp->sl.prox;
175 <        newsrc->sa.svnext = sp - source;
176 <        return(newsrc);
172 >        copystruct(source[i].sl.s, &ourspot);
173 >        if (nsflags & SPROX)
174 >                source[i].sl.prox = source[sn].sl.prox;
175 >        source[i].sa.svnext = sn;
176 >        source[i].so = op;
177 >        return(i);
178   memerr:
179          error(SYSTEM, "out of memory in makevsrc");
180   }
181  
182  
183 + double
184 + getdisk(oc, op, sn)             /* get visible object disk */
185 + FVECT  oc;
186 + OBJREC  *op;
187 + register int  sn;
188 + {
189 +        double  rad2, roffs, offs, d, rd, rdoto;
190 +        FVECT  rnrm, nrm;
191 +                                /* first, use object getdisk function */
192 +        rad2 = (*sfun[op->otype].of->getdisk)(oc, op);
193 +        if (!(source[sn].sflags & SVIRTUAL))
194 +                return(rad2);           /* all done for normal source */
195 +                                /* check for correct side of relay surface */
196 +        roffs = (*sfun[source[sn].so->otype].of->getpleq)(rnrm, source[sn].so);
197 +        rd = DOT(rnrm, source[sn].sloc);        /* source projection */
198 +        if (!(source[sn].sflags & SDISTANT))
199 +                rd -= roffs;
200 +        d = DOT(rnrm, oc) - roffs;      /* disk distance to relay plane */
201 +        if ((d > 0.) ^ (rd > 0.))
202 +                return(rad2);           /* OK if opposite sides */
203 +        if (d*d >= rad2)
204 +                return(.0);             /* no relay is possible */
205 +                                /* we need a closer look */
206 +        offs = (*sfun[op->otype].of->getpleq)(nrm, op);
207 +        rdoto = DOT(rnrm, nrm);
208 +        if (d*d >= rad2*(1.-rdoto*rdoto))
209 +                return(0.);             /* disk entirely on projection side */
210 +                                /* should shrink disk but I'm lazy */
211 +        return(rad2);
212 + }
213 +
214 +
215   commonspot(sp1, sp2, org)       /* set sp1 to intersection of sp1 and sp2 */
216   register SPOT  *sp1, *sp2;
217   FVECT  org;
# Line 214 | Line 274 | FVECT  nrm;
274   }
275  
276  
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
277   double
278   intercircle(cc, c1, c2, r1s, r2s)       /* intersect two circles */
279   FVECT  cc;                      /* midpoint (return value) */
# Line 267 | Line 311 | double  r1s, r2s;              /* radii squared */
311   }
312  
313  
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;
314   #ifdef DEBUG
315 <        default:
316 <                error(CONSISTENCY, "inappropriate material in vsrcrelay");
317 < #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;
315 > virtverb(sn, fp)        /* print verbose description of virtual source */
316 > register int  sn;
317 > FILE  *fp;
318   {
396        COLOR  mcolor;
397        RAY  nr;
319          register int  i;
320  
321 <        if (m->oargs.nfargs != 3 || m->oargs.nsargs > 1)
322 <                objerror(m, USER, "bad number of arguments");
323 <        if (r->rsrc >= 0) {                     /* aiming for somebody */
324 <                if (source[r->rsrc].so != r->ro)
325 <                        return;                         /* but not us */
326 <        } else if (m->oargs.nsargs > 0) {       /* else call substitute? */
327 <                rayshade(r, modifier(m->oargs.sarg[0]));
321 >        fprintf(fp, "%s virtual source %d in %s %s\n",
322 >                        source[sn].sflags & SDISTANT ? "distant" : "local",
323 >                        sn, ofun[source[sn].so->otype].funame,
324 >                        source[sn].so->oname);
325 >        fprintf(fp, "\tat (%f,%f,%f)\n",
326 >                source[sn].sloc[0], source[sn].sloc[1], source[sn].sloc[2]);
327 >        fprintf(fp, "\tlinked to source %d (%s)\n",
328 >                source[sn].sa.svnext, source[source[sn].sa.svnext].so->oname);
329 >        if (source[sn].sflags & SFOLLOW)
330 >                fprintf(fp, "\talways followed\n");
331 >        else
332 >                fprintf(fp, "\tnever followed\n");
333 >        if (!(source[sn].sflags & SSPOT))
334                  return;
335 <        }
336 <        if (r->rod < 0.)                        /* back is black */
337 <                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);
335 >        fprintf(fp, "\twith spot aim (%f,%f,%f) and size %f\n",
336 >                        source[sn].sl.s->aim[0], source[sn].sl.s->aim[1],
337 >                        source[sn].sl.s->aim[2], source[sn].sl.s->siz);
338   }
339 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines