ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/srcdraw.c
Revision: 2.9
Committed: Wed Oct 1 22:07:19 2003 UTC (20 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.8: +9 -6 lines
Log Message:
Fixed old problem with drawsources and illum's

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.9 static const char RCSid[] = "$Id: srcdraw.c,v 2.8 2003/07/27 22:12:03 schorsch Exp $";
3 greg 2.1 #endif
4     /*
5     * Draw small sources into image in case we missed them.
6 greg 2.5 *
7     * External symbols declared in ray.h
8     */
9    
10 greg 2.6 #include "copyright.h"
11 greg 2.1
12     #include "ray.h"
13    
14     #include "view.h"
15    
16     #include "source.h"
17    
18    
19     #define CLIP_ABOVE 1
20     #define CLIP_BELOW 2
21     #define CLIP_RIGHT 3
22     #define CLIP_LEFT 4
23    
24     #define MAXVERT 10
25    
26 greg 2.3 typedef struct splist {
27     struct splist *next; /* next source in list */
28     int sn; /* source number */
29     short nv; /* number of vertices */
30 schorsch 2.7 RREAL vl[3][2]; /* vertex array (last) */
31 greg 2.3 } SPLIST; /* source polygon list */
32 greg 2.1
33 greg 2.3 extern VIEW ourview; /* our view parameters */
34     extern int hres, vres; /* our image resolution */
35     static SPLIST *sphead = NULL; /* our list of source polys */
36    
37    
38 greg 2.1 static int
39     inregion(p, cv, crit) /* check if vertex is in region */
40 schorsch 2.7 RREAL p[2];
41 greg 2.1 double cv;
42     int crit;
43     {
44     switch (crit) {
45     case CLIP_ABOVE:
46     return(p[1] < cv);
47     case CLIP_BELOW:
48     return(p[1] >= cv);
49     case CLIP_RIGHT:
50     return(p[0] < cv);
51     case CLIP_LEFT:
52     return(p[0] >= cv);
53     }
54     return(-1);
55     }
56    
57    
58     static
59     clipregion(a, b, cv, crit, r) /* find intersection with boundary */
60 schorsch 2.7 register RREAL a[2], b[2];
61 greg 2.1 double cv;
62     int crit;
63 schorsch 2.7 RREAL r[2]; /* return value */
64 greg 2.1 {
65     switch (crit) {
66     case CLIP_ABOVE:
67     case CLIP_BELOW:
68     r[1] = cv;
69     r[0] = a[0] + (cv-a[1])/(b[1]-a[1])*(b[0]-a[0]);
70     return;
71     case CLIP_RIGHT:
72     case CLIP_LEFT:
73     r[0] = cv;
74     r[1] = a[1] + (cv-a[0])/(b[0]-a[0])*(b[1]-a[1]);
75     return;
76     }
77     }
78    
79    
80     static int
81     hp_clip_poly(vl, nv, cv, crit, vlo) /* clip polygon to half-plane */
82 schorsch 2.7 RREAL vl[][2];
83 greg 2.1 int nv;
84     double cv;
85     int crit;
86 schorsch 2.7 RREAL vlo[][2]; /* return value */
87 greg 2.1 {
88 schorsch 2.7 RREAL *s, *p;
89 greg 2.1 register int j, nvo;
90    
91     s = vl[nv-1];
92     nvo = 0;
93     for (j = 0; j < nv; j++) {
94     p = vl[j];
95     if (inregion(p, cv, crit)) {
96     if (!inregion(s, cv, crit))
97     clipregion(s, p, cv, crit, vlo[nvo++]);
98     vlo[nvo][0] = p[0]; vlo[nvo++][1] = p[1];
99     } else if (inregion(s, cv, crit))
100     clipregion(s, p, cv, crit, vlo[nvo++]);
101     s = p;
102     }
103     return(nvo);
104     }
105    
106    
107     static int
108     box_clip_poly(vl, nv, xl, xr, yb, ya, vlo) /* clip polygon to box */
109 schorsch 2.7 RREAL vl[MAXVERT][2];
110 greg 2.1 int nv;
111     double xl, xr, yb, ya;
112 schorsch 2.7 RREAL vlo[MAXVERT][2]; /* return value */
113 greg 2.1 {
114 schorsch 2.7 RREAL vlt[MAXVERT][2];
115 greg 2.1 int nvt, nvo;
116    
117     nvt = hp_clip_poly(vl, nv, yb, CLIP_BELOW, vlt);
118     nvo = hp_clip_poly(vlt, nvt, ya, CLIP_ABOVE, vlo);
119     nvt = hp_clip_poly(vlo, nvo, xl, CLIP_LEFT, vlt);
120     nvo = hp_clip_poly(vlt, nvt, xr, CLIP_RIGHT, vlo);
121    
122     return(nvo);
123     }
124    
125    
126     static double
127     minw2(vl, nv, ar2) /* compute square of minimum width */
128 schorsch 2.7 RREAL vl[][2];
129 greg 2.1 int nv;
130     double ar2;
131     {
132     double d2, w2, w2min, w2max;
133 schorsch 2.7 register RREAL *p0, *p1, *p2;
134 greg 2.1 int i, j;
135     /* find minimum for all widths */
136     w2min = FHUGE;
137     p0 = vl[nv-1];
138     for (i = 0; i < nv; i++) { /* for each edge */
139     p1 = vl[i];
140     d2 = (p1[0]-p0[0])*(p1[0]-p0[0]) +
141     (p1[1]-p0[1])*(p1[1]-p0[1])*ar2;
142     w2max = 0.; /* find maximum for this side */
143     for (j = 1; j < nv-1; j++) {
144     p2 = vl[(i+j)%nv];
145     w2 = (p1[0]-p0[0])*(p2[1]-p0[1]) -
146     (p1[1]-p0[1])*(p2[0]-p0[0]);
147     w2 = w2*w2*ar2/d2; /* triangle height squared */
148     if (w2 > w2max)
149     w2max = w2;
150     }
151     if (w2max < w2min) /* global min. based on local max.'s */
152     w2min = w2max;
153     p0 = p1;
154     }
155     return(w2min);
156     }
157    
158    
159     static
160     convex_center(vl, nv, cv) /* compute center of convex polygon */
161 schorsch 2.7 register RREAL vl[][2];
162 greg 2.1 int nv;
163 schorsch 2.7 RREAL cv[2]; /* return value */
164 greg 2.1 {
165     register int i;
166     /* simple average (suboptimal) */
167     cv[0] = cv[1] = 0.;
168     for (i = 0; i < nv; i++) {
169     cv[0] += vl[i][0];
170     cv[1] += vl[i][1];
171     }
172     cv[0] /= (double)nv;
173     cv[1] /= (double)nv;
174     }
175    
176    
177     static double
178     poly_area(vl, nv) /* compute area of polygon */
179 schorsch 2.7 register RREAL vl[][2];
180 greg 2.1 int nv;
181     {
182     double a;
183 schorsch 2.7 RREAL v0[2], v1[2];
184 greg 2.1 register int i;
185    
186     a = 0.;
187     v0[0] = vl[1][0] - vl[0][0];
188     v0[1] = vl[1][1] - vl[0][1];
189     for (i = 2; i < nv; i++) {
190     v1[0] = vl[i][0] - vl[0][0];
191     v1[1] = vl[i][1] - vl[0][1];
192     a += v0[0]*v1[1] - v0[1]*v1[0];
193     v0[0] = v1[0]; v0[1] = v1[1];
194     }
195     return(a * (a >= 0. ? .5 : -.5));
196     }
197    
198    
199     static int
200     convex_hull(vl, nv, vlo) /* compute polygon's convex hull */
201 schorsch 2.7 RREAL vl[][2];
202 greg 2.1 int nv;
203 schorsch 2.7 RREAL vlo[][2]; /* return value */
204 greg 2.1 {
205     int nvo, nvt;
206 schorsch 2.7 RREAL vlt[MAXVERT][2];
207 greg 2.1 double voa, vta;
208     register int i, j;
209     /* start with original polygon */
210     for (i = nvo = nv; i--; ) {
211     vlo[i][0] = vl[i][0]; vlo[i][1] = vl[i][1];
212     }
213     voa = poly_area(vlo, nvo); /* compute its area */
214     for (i = 0; i < nvo; i++) { /* for each output vertex */
215     for (j = 0; j < i; j++) {
216     vlt[j][0] = vlo[j][0]; vlt[j][1] = vlo[j][1];
217     }
218     nvt = nvo - 1; /* make poly w/o vertex */
219     for (j = i; j < nvt; j++) {
220     vlt[j][0] = vlo[j+1][0]; vlt[j][1] = vlo[j+1][1];
221     }
222     vta = poly_area(vlt, nvt);
223     if (vta >= voa) { /* is simpler poly bigger? */
224     voa = vta; /* then use it */
225     for (j = nvo = nvt; j--; ) {
226     vlo[j][0] = vlt[j][0]; vlo[j][1] = vlt[j][1];
227     }
228     i--; /* next adjust */
229     }
230     }
231     return(nvo);
232     }
233    
234    
235 greg 2.3 static
236     spinsert(sn, vl, nv) /* insert new source polygon */
237     int sn;
238 schorsch 2.7 RREAL vl[][2];
239 greg 2.3 int nv;
240     {
241     register SPLIST *spn;
242     register int i;
243    
244     if (nv < 3)
245     return;
246     if (nv > 3)
247 schorsch 2.7 spn = (SPLIST *)malloc(sizeof(SPLIST)+sizeof(RREAL)*2*(nv-3));
248 greg 2.3 else
249     spn = (SPLIST *)malloc(sizeof(SPLIST));
250     if (spn == NULL)
251     error(SYSTEM, "out of memory in spinsert");
252     spn->sn = sn;
253     for (i = spn->nv = nv; i--; ) {
254     spn->vl[i][0] = vl[i][0]; spn->vl[i][1] = vl[i][1];
255     }
256     spn->next = sphead; /* push onto global list */
257     sphead = spn;
258     }
259    
260    
261 greg 2.1 int
262 greg 2.3 sourcepoly(sn, sp) /* compute image polygon for source */
263 greg 2.1 int sn;
264 schorsch 2.7 RREAL sp[MAXVERT][2];
265 greg 2.1 {
266 greg 2.9 static short cubeord[8][6] = {{1,3,2,6,4,5},{0,4,5,7,3,2},
267 greg 2.1 {0,1,3,7,6,4},{0,1,5,7,6,2},
268     {0,2,6,7,5,1},{0,4,6,7,3,1},
269     {0,2,3,7,5,4},{1,5,4,6,2,3}};
270     register SRCREC *s = source + sn;
271     FVECT ap, ip;
272 schorsch 2.7 RREAL pt[6][2];
273 greg 2.1 int dir;
274     register int i, j;
275    
276     if (s->sflags & (SDISTANT|SFLAT)) {
277 greg 2.3 if (s->sflags & SDISTANT && ourview.type == VT_PAR)
278 greg 2.1 return(0); /* all or nothing case */
279     if (s->sflags & SFLAT) {
280     for (i = 0; i < 3; i++)
281 greg 2.3 ap[i] = s->sloc[i] - ourview.vp[i];
282 greg 2.1 if (DOT(ap, s->snorm) >= 0.)
283     return(0); /* source faces away */
284     }
285     for (j = 0; j < 4; j++) { /* four corners */
286     for (i = 0; i < 3; i++) {
287     ap[i] = s->sloc[i];
288 schorsch 2.8 if ((j==1)|(j==2)) ap[i] += s->ss[SU][i];
289 greg 2.1 else ap[i] -= s->ss[SU][i];
290 schorsch 2.8 if ((j==2)|(j==3)) ap[i] += s->ss[SV][i];
291 greg 2.1 else ap[i] -= s->ss[SV][i];
292     if (s->sflags & SDISTANT) {
293 greg 2.3 ap[i] *= 1. + ourview.vfore;
294     ap[i] += ourview.vp[i];
295 greg 2.1 }
296     }
297 greg 2.3 viewloc(ip, &ourview, ap); /* find image point */
298 greg 2.1 if (ip[2] <= 0.)
299     return(0); /* in front of view */
300     sp[j][0] = ip[0]; sp[j][1] = ip[1];
301     }
302     return(4);
303     }
304     /* identify furthest corner */
305     for (i = 0; i < 3; i++)
306 greg 2.3 ap[i] = s->sloc[i] - ourview.vp[i];
307 greg 2.1 dir = (DOT(ap,s->ss[SU])>0.) |
308     (DOT(ap,s->ss[SV])>0.)<<1 |
309     (DOT(ap,s->ss[SW])>0.)<<2 ;
310     /* order vertices based on this */
311     for (j = 0; j < 6; j++) {
312     for (i = 0; i < 3; i++) {
313     ap[i] = s->sloc[i];
314     if (cubeord[dir][j] & 1) ap[i] += s->ss[SU][i];
315     else ap[i] -= s->ss[SU][i];
316     if (cubeord[dir][j] & 2) ap[i] += s->ss[SV][i];
317     else ap[i] -= s->ss[SV][i];
318     if (cubeord[dir][j] & 4) ap[i] += s->ss[SW][i];
319     else ap[i] -= s->ss[SW][i];
320     }
321 greg 2.3 viewloc(ip, &ourview, ap); /* find image point */
322 greg 2.1 if (ip[2] <= 0.)
323     return(0); /* in front of view */
324     pt[j][0] = ip[0]; pt[j][1] = ip[1];
325     }
326     return(convex_hull(pt, 6, sp)); /* make sure it's convex */
327     }
328    
329    
330 greg 2.3 /* initialize by finding sources smaller than rad */
331     init_drawsources(rad)
332     int rad; /* source sample size */
333     {
334 schorsch 2.7 RREAL spoly[MAXVERT][2];
335 greg 2.3 int nsv;
336     register SPLIST *sp;
337     register int i;
338     /* free old source list if one */
339     for (sp = sphead; sp != NULL; sp = sphead) {
340     sphead = sp->next;
341 greg 2.5 free((void *)sp);
342 greg 2.3 }
343     /* loop through all sources */
344     for (i = nsources; i--; ) {
345     /* compute image polygon for source */
346     if (!(nsv = sourcepoly(i, spoly)))
347     continue;
348     /* clip to image boundaries */
349     if (!(nsv = box_clip_poly(spoly, nsv, 0., 1., 0., 1., spoly)))
350     continue;
351     /* big enough for standard sampling? */
352     if (minw2(spoly, nsv, ourview.vn2/ourview.hn2) >
353     (double)rad*rad/hres/hres)
354     continue;
355     /* OK, add to our list */
356     spinsert(i, spoly, nsv);
357     }
358     }
359    
360 greg 2.5 void /* add sources smaller than rad to computed subimage */
361 greg 2.3 drawsources(pic, zbf, x0, xsiz, y0, ysiz)
362 greg 2.1 COLOR *pic[]; /* subimage pixel value array */
363     float *zbf[]; /* subimage distance array (opt.) */
364     int x0, xsiz, y0, ysiz; /* origin and size of subimage */
365     {
366 schorsch 2.7 RREAL spoly[MAXVERT][2], ppoly[MAXVERT][2];
367 greg 2.1 int nsv, npv;
368 greg 2.3 int xmin, xmax, ymin, ymax, x, y;
369 schorsch 2.7 RREAL cxy[2];
370 gregl 2.4 double w;
371 greg 2.1 RAY sr;
372 greg 2.3 register SPLIST *sp;
373     register int i;
374     /* check each source in our list */
375     for (sp = sphead; sp != NULL; sp = sp->next) {
376 greg 2.1 /* clip source poly to subimage */
377 greg 2.3 nsv = box_clip_poly(sp->vl, sp->nv,
378     (double)x0/hres, (double)(x0+xsiz)/hres,
379     (double)y0/vres, (double)(y0+ysiz)/vres, spoly);
380 greg 2.1 if (!nsv)
381     continue;
382     /* find common subimage (BBox) */
383     xmin = x0 + xsiz; xmax = x0;
384     ymin = y0 + ysiz; ymax = y0;
385     for (i = 0; i < nsv; i++) {
386 greg 2.3 if ((double)xmin/hres > spoly[i][0])
387     xmin = spoly[i][0]*hres + FTINY;
388     if ((double)xmax/hres < spoly[i][0])
389     xmax = spoly[i][0]*hres - FTINY;
390     if ((double)ymin/vres > spoly[i][1])
391     ymin = spoly[i][1]*vres + FTINY;
392     if ((double)ymax/vres < spoly[i][1])
393     ymax = spoly[i][1]*vres - FTINY;
394 greg 2.1 }
395     /* evaluate each pixel in BBox */
396     for (y = ymin; y <= ymax; y++)
397     for (x = xmin; x <= xmax; x++) {
398     /* subarea for pixel */
399     npv = box_clip_poly(spoly, nsv,
400 greg 2.3 (double)x/hres, (x+1.)/hres,
401     (double)y/vres, (y+1.)/vres,
402     ppoly);
403 greg 2.1 if (!npv)
404     continue; /* no overlap */
405     convex_center(ppoly, npv, cxy);
406 greg 2.3 if ((sr.rmax = viewray(sr.rorg,sr.rdir,&ourview,
407     cxy[0],cxy[1])) < -FTINY)
408 greg 2.1 continue; /* not in view */
409 greg 2.3 if (source[sp->sn].sflags & SSPOT &&
410     spotout(&sr, source[sp->sn].sl.s))
411 greg 2.1 continue; /* outside spot */
412 greg 2.9 w = poly_area(ppoly, npv) * hres * vres;
413     if (w < .95) { /* subpixel source */
414     rayorigin(&sr, NULL, SHADOW, 1.0);
415     sr.rsrc = sp->sn;
416     } else
417     rayorigin(&sr, NULL, PRIMARY, 1.0);
418 greg 2.1 rayvalue(&sr); /* compute value */
419     if (bright(sr.rcol) <= FTINY)
420     continue; /* missed/blocked */
421     /* modify pixel */
422     if (zbf[y-y0] != NULL &&
423 gregl 2.4 sr.rt < 0.999*zbf[y-y0][x-x0])
424 greg 2.1 zbf[y-y0][x-x0] = sr.rt;
425 gregl 2.4 else if (!bigdiff(sr.rcol, pic[y-y0][x-x0],
426 greg 2.9 0.01)) /* source sample */
427 gregl 2.4 setcolor(pic[y-y0][x-x0], 0., 0., 0.);
428     scalecolor(sr.rcol, w);
429     scalecolor(pic[y-y0][x-x0], 1.-w);
430 greg 2.1 addcolor(pic[y-y0][x-x0], sr.rcol);
431     }
432     }
433     }