ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/srcdraw.c
Revision: 2.19
Committed: Thu Nov 8 00:54:07 2018 UTC (5 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.18: +2 -1 lines
Log Message:
Moved findmaterial() from source.c to initotypes.c

File Contents

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