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.3 by greg, Thu Jun 20 13:43:38 1991 UTC vs.
Revision 1.6 by greg, Fri Jun 21 13:25:42 1991 UTC

# Line 15 | Line 15 | static char SCCSid[] = "$SunId$ LBL";
15  
16   #include  "source.h"
17  
18 #include  "cone.h"
18  
19 < #include  "face.h"
19 > double  intercircle(), getdisk();
20  
22
23 double  intercircle();
24 SRCREC  *makevsrc();
25
21   static OBJECT  *vobject;                /* virtual source objects */
22   static int  nvobjects = 0;              /* number of virtual source objects */
23  
# 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 76 | Line 74 | int  nr;
74                                  /* check each virtual object for projection */
75          for (i = 0; i < nvobjects; i++)
76                                          /* vproject() calls us recursively */
77 <                vproject(objptr(i), sr, nr-1);
77 >                vproject(objptr(vobject[i]), sn, nr-1);
78   }
79  
80  
81 < vproject(o, s, n)               /* create projected source(s) if they exist */
81 > vproject(o, sn, n)              /* create projected source(s) if they exist */
82   OBJREC  *o;
83 < SRCREC  *s;
83 > int  sn;
84   int  n;
85   {
86          register int  i;
87          register VSMATERIAL  *vsmat;
88          MAT4  proj;
89 <        SRCREC  *ns;
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, s, i))
98 <                        if ((ns = makevsrc(o, s, proj)) != NULL)
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 < SRCREC *
108 < makevsrc(op, sp, pm)            /* make virtual source if reasonable */
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;
109 <        FVECT  nsloc, ocent, nsnorm;
110 <        int  nsflags;
113 >        FVECT  nsloc, nsnorm, ocent;
114          double  maxrad2;
115 +        int  nsflags;
116          double  d1;
117          SPOT  theirspot, ourspot;
118          register int  i;
119  
120 <        nsflags = (sp->sflags|(SVIRTUAL|SFOLLOW)) & ~SSPOT;
120 >        nsflags = source[sn].sflags | (SVIRTUAL|SSPOT|SFOLLOW);
121                                          /* get object center and max. radius */
122 <        if (sfun[op->otype].of->getdisk != NULL) {
123 <                maxrad2 = (*sfun[op->otype].of->getdisk)(ocent, op);
124 <                if (maxrad2 <= FTINY)                   /* too small? */
121 <                        return(NULL);
122 <                nsflags |= SSPOT;
123 <        }
122 >        maxrad2 = getdisk(ocent, op, sn);
123 >        if (maxrad2 <= FTINY)                   /* too small? */
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);
130 <                if (nsflags & SSPOT) {
131 <                        VCOPY(ourspot.aim, ocent);
132 <                        ourspot.siz = PI*maxrad2;
133 <                        ourspot.flen = 0.;
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 (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(-1);             /* no overlap */
138                  }
134                if (sp->sflags & SSPOT) {
135                        copystruct(&theirspot, sp->sl.s);
136                        multp3(theirspot.aim, sp->sl.s->aim, pm);
137                        if (nsflags & SSPOT &&
138                                !commonbeam(&ourspot, &theirspot, nsloc))
139                                return(NULL);           /* no overlap */
140                }
139          } else {                                /* local source */
140 <                multp3(nsloc, sp->sloc, pm);
141 <                if (nsflags & SSPOT) {
142 <                        for (i = 0; i < 3; i++)
143 <                                ourspot.aim[i] = ocent[i] - nsloc[i];
144 <                        if ((d1 = normalize(ourspot.aim)) == 0.)
145 <                                return(NULL);           /* at source!! */
146 <                        if (sp->sflags & SPROX && d1 > sp->sl.prox)
147 <                                return(NULL);           /* too far away */
148 <                        ourspot.siz = 2.*PI*(1. - d1/sqrt(d1*d1+maxrad2));
149 <                        ourspot.flen = 0.;
150 <                } else if (sp->sflags & SPROX) {
151 <                        FVECT  norm;
152 <                        double  offs;
153 <                                                /* use distance from plane */
154 <                        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 */
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(-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 (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(-1);     /* no overlap */
154 >                        ourspot.flen = theirspot.flen;
155                  }
156 <                if (sp->sflags & SSPOT) {
157 <                        copystruct(&theirspot, sp->sl.s);
158 <                        multv3(theirspot.aim, sp->sl.s->aim, pm);
159 <                        if (nsflags & SSPOT) {
165 <                                if (!commonspot(&ourspot, &theirspot, nsloc))
166 <                                        return(NULL);   /* no overlap */
167 <                                ourspot.flen = theirspot.flen;
168 <                        }
156 >                if (source[sn].sflags & SFLAT) {        /* behind source? */
157 >                        multv3(nsnorm, source[sn].snorm, pm);
158 >                        if (checkspot(&ourspot, nsnorm) < 0)
159 >                                return(-1);
160                  }
170                if (sp->sflags & SFLAT) {       /* check for behind source */
171                        multv3(nsnorm, sp->snorm, pm);
172                        if (nsflags & SSPOT && checkspot(&ourspot, nsnorm) < 0)
173                                return(NULL);
174                }
161          }
162                                          /* everything is OK, make source */
163 <        if ((newsrc = newsource()) == NULL)
163 >        if ((i = newsource()) < 0)
164                  goto memerr;
165 <        newsrc->sflags = nsflags;
166 <        VCOPY(newsrc->sloc, nsloc);
165 >        source[i].sflags = nsflags;
166 >        VCOPY(source[i].sloc, nsloc);
167          if (nsflags & SFLAT)
168 <                VCOPY(newsrc->snorm, nsnorm);
169 <        newsrc->ss = sp->ss; newsrc->ss2 = sp->ss2;
170 <        if ((nsflags | sp->sflags) & SSPOT) {
171 <                if ((newsrc->sl.s = (SPOT *)malloc(sizeof(SPOT))) == NULL)
172 <                        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 <        }
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(source[i].sl.s, &ourspot);
173          if (nsflags & SPROX)
174 <                newsrc->sl.prox = sp->sl.prox;
175 <        newsrc->sa.svnext = sp - source;
176 <        return(newsrc);
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 296 | Line 309 | double  r1s, r2s;              /* radii squared */
309                  cc[i] = c1[i] + l*disp[i];
310          return(a2);
311   }
312 +
313 +
314 + #ifdef DEBUG
315 + virtverb(sn, fp)        /* print verbose description of virtual source */
316 + register int  sn;
317 + FILE  *fp;
318 + {
319 +        register int  i;
320 +
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 +        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