ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/srcdraw.c
Revision: 2.7
Committed: Thu Jun 26 00:58:10 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.6: +27 -27 lines
Log Message:
Abstracted process and path handling for Windows.
Renamed FLOAT to RREAL because of conflict on Windows.
Added conditional compiles for some signal handlers.

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: srcdraw.c,v 2.6 2003/02/25 02:47:23 greg Exp $";
3 #endif
4 /*
5 * Draw small sources into image in case we missed them.
6 *
7 * External symbols declared in ray.h
8 */
9
10 #include "copyright.h"
11
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 typedef struct splist {
27 struct splist *next; /* next source in list */
28 int sn; /* source number */
29 short nv; /* number of vertices */
30 RREAL vl[3][2]; /* vertex array (last) */
31 } SPLIST; /* source polygon list */
32
33 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 static int
39 inregion(p, cv, crit) /* check if vertex is in region */
40 RREAL p[2];
41 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 register RREAL a[2], b[2];
61 double cv;
62 int crit;
63 RREAL r[2]; /* return value */
64 {
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 RREAL vl[][2];
83 int nv;
84 double cv;
85 int crit;
86 RREAL vlo[][2]; /* return value */
87 {
88 RREAL *s, *p;
89 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 RREAL vl[MAXVERT][2];
110 int nv;
111 double xl, xr, yb, ya;
112 RREAL vlo[MAXVERT][2]; /* return value */
113 {
114 RREAL vlt[MAXVERT][2];
115 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 RREAL vl[][2];
129 int nv;
130 double ar2;
131 {
132 double d2, w2, w2min, w2max;
133 register RREAL *p0, *p1, *p2;
134 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 register RREAL vl[][2];
162 int nv;
163 RREAL cv[2]; /* return value */
164 {
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 register RREAL vl[][2];
180 int nv;
181 {
182 double a;
183 RREAL v0[2], v1[2];
184 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 RREAL vl[][2];
202 int nv;
203 RREAL vlo[][2]; /* return value */
204 {
205 int nvo, nvt;
206 RREAL vlt[MAXVERT][2];
207 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 static
236 spinsert(sn, vl, nv) /* insert new source polygon */
237 int sn;
238 RREAL vl[][2];
239 int nv;
240 {
241 register SPLIST *spn;
242 register int i;
243
244 if (nv < 3)
245 return;
246 if (nv > 3)
247 spn = (SPLIST *)malloc(sizeof(SPLIST)+sizeof(RREAL)*2*(nv-3));
248 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 int
262 sourcepoly(sn, sp) /* compute image polygon for source */
263 int sn;
264 RREAL sp[MAXVERT][2];
265 {
266 static char cubeord[8][6] = {{1,3,2,6,4,5},{0,4,5,7,3,2},
267 {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 RREAL pt[6][2];
273 int dir;
274 register int i, j;
275
276 if (s->sflags & (SDISTANT|SFLAT)) {
277 if (s->sflags & SDISTANT && ourview.type == VT_PAR)
278 return(0); /* all or nothing case */
279 if (s->sflags & SFLAT) {
280 for (i = 0; i < 3; i++)
281 ap[i] = s->sloc[i] - ourview.vp[i];
282 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 if (j==1|j==2) ap[i] += s->ss[SU][i];
289 else ap[i] -= s->ss[SU][i];
290 if (j==2|j==3) ap[i] += s->ss[SV][i];
291 else ap[i] -= s->ss[SV][i];
292 if (s->sflags & SDISTANT) {
293 ap[i] *= 1. + ourview.vfore;
294 ap[i] += ourview.vp[i];
295 }
296 }
297 viewloc(ip, &ourview, ap); /* find image point */
298 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 ap[i] = s->sloc[i] - ourview.vp[i];
307 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 viewloc(ip, &ourview, ap); /* find image point */
322 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 /* initialize by finding sources smaller than rad */
331 init_drawsources(rad)
332 int rad; /* source sample size */
333 {
334 RREAL spoly[MAXVERT][2];
335 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 free((void *)sp);
342 }
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 void /* add sources smaller than rad to computed subimage */
361 drawsources(pic, zbf, x0, xsiz, y0, ysiz)
362 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 RREAL spoly[MAXVERT][2], ppoly[MAXVERT][2];
367 int nsv, npv;
368 int xmin, xmax, ymin, ymax, x, y;
369 RREAL cxy[2];
370 double w;
371 RAY sr;
372 register SPLIST *sp;
373 register int i;
374 /* check each source in our list */
375 for (sp = sphead; sp != NULL; sp = sp->next) {
376 /* clip source poly to subimage */
377 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 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 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 }
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 (double)x/hres, (x+1.)/hres,
401 (double)y/vres, (y+1.)/vres,
402 ppoly);
403 if (!npv)
404 continue; /* no overlap */
405 convex_center(ppoly, npv, cxy);
406 if ((sr.rmax = viewray(sr.rorg,sr.rdir,&ourview,
407 cxy[0],cxy[1])) < -FTINY)
408 continue; /* not in view */
409 if (source[sp->sn].sflags & SSPOT &&
410 spotout(&sr, source[sp->sn].sl.s))
411 continue; /* outside spot */
412 rayorigin(&sr, NULL, SHADOW, 1.0);
413 sr.rsrc = sp->sn;
414 rayvalue(&sr); /* compute value */
415 if (bright(sr.rcol) <= FTINY)
416 continue; /* missed/blocked */
417 /* modify pixel */
418 if (zbf[y-y0] != NULL &&
419 sr.rt < 0.999*zbf[y-y0][x-x0])
420 zbf[y-y0][x-x0] = sr.rt;
421 else if (!bigdiff(sr.rcol, pic[y-y0][x-x0],
422 0.001)) /* source sample */
423 setcolor(pic[y-y0][x-x0], 0., 0., 0.);
424 w = poly_area(ppoly, npv) * hres * vres;
425 scalecolor(sr.rcol, w);
426 scalecolor(pic[y-y0][x-x0], 1.-w);
427 addcolor(pic[y-y0][x-x0], sr.rcol);
428 }
429 }
430 }