ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/image.c
Revision: 1.16
Committed: Thu Nov 7 11:04:00 1991 UTC (32 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.15: +10 -9 lines
Log Message:
added badarg() routine for argument checking

File Contents

# User Rev Content
1 greg 1.1 /* Copyright (c) 1986 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * image.c - routines for image generation.
9     *
10     * 10/17/85
11     */
12    
13     #include "standard.h"
14    
15     #include "view.h"
16    
17 greg 1.5 VIEW stdview = STDVIEW; /* default view parameters */
18 greg 1.1
19    
20     char *
21 greg 1.5 setview(v) /* set hvec and vvec, return message on error */
22     register VIEW *v;
23 greg 1.3 {
24 greg 1.12 static char ill_horiz[] = "illegal horizontal view size";
25     static char ill_vert[] = "illegal vertical view size";
26    
27 greg 1.1 if (normalize(v->vdir) == 0.0) /* normalize direction */
28     return("zero view direction");
29    
30 greg 1.14 if (normalize(v->vup) == 0.0) /* normalize view up */
31     return("zero view up vector");
32    
33 greg 1.5 fcross(v->hvec, v->vdir, v->vup); /* compute horiz dir */
34    
35     if (normalize(v->hvec) == 0.0)
36 greg 1.14 return("view up parallel to view direction");
37 greg 1.1
38 greg 1.5 fcross(v->vvec, v->hvec, v->vdir); /* compute vert dir */
39    
40 greg 1.12 if (v->horiz <= FTINY)
41     return(ill_horiz);
42     if (v->vert <= FTINY)
43     return(ill_vert);
44    
45     switch (v->type) {
46     case VT_PAR: /* parallel view */
47 greg 1.5 v->hn2 = v->horiz;
48 greg 1.12 v->vn2 = v->vert;
49     break;
50     case VT_PER: /* perspective view */
51     if (v->horiz >= 180.0-FTINY)
52     return(ill_horiz);
53     if (v->vert >= 180.0-FTINY)
54     return(ill_vert);
55 greg 1.5 v->hn2 = 2.0 * tan(v->horiz*(PI/180.0/2.0));
56 greg 1.12 v->vn2 = 2.0 * tan(v->vert*(PI/180.0/2.0));
57     break;
58     case VT_ANG: /* angular fisheye */
59     if (v->horiz > 360.0+FTINY)
60     return(ill_horiz);
61     if (v->vert > 360.0+FTINY)
62     return(ill_vert);
63     v->hn2 = v->horiz / 90.0;
64     v->vn2 = v->vert / 90.0;
65     break;
66     case VT_HEM: /* hemispherical fisheye */
67     if (v->horiz > 180.0+FTINY)
68     return(ill_horiz);
69     if (v->vert > 180.0+FTINY)
70     return(ill_vert);
71     v->hn2 = 2.0 * sin(v->horiz*(PI/180.0/2.0));
72     v->vn2 = 2.0 * sin(v->vert*(PI/180.0/2.0));
73     break;
74     default:
75 greg 1.1 return("unknown view type");
76 greg 1.12 }
77 greg 1.13 if (v->type != VT_ANG) {
78 greg 1.12 v->hvec[0] *= v->hn2;
79     v->hvec[1] *= v->hn2;
80     v->hvec[2] *= v->hn2;
81     v->vvec[0] *= v->vn2;
82     v->vvec[1] *= v->vn2;
83     v->vvec[2] *= v->vn2;
84     }
85 greg 1.5 v->hn2 *= v->hn2;
86     v->vn2 *= v->vn2;
87 greg 1.1
88     return(NULL);
89     }
90    
91    
92 greg 1.7 normaspect(va, ap, xp, yp) /* fix pixel aspect or resolution */
93     double va; /* view aspect ratio */
94     double *ap; /* pixel aspect in (or out if 0) */
95     int *xp, *yp; /* x and y resolution in (or out if *ap!=0) */
96 greg 1.6 {
97     if (*ap <= FTINY)
98 greg 1.7 *ap = va * *xp / *yp; /* compute pixel aspect */
99 greg 1.6 else if (va * *xp > *ap * *yp)
100 greg 1.10 *xp = *yp / va * *ap + .5; /* reduce x resolution */
101 greg 1.6 else
102 greg 1.10 *yp = *xp * va / *ap + .5; /* reduce y resolution */
103 greg 1.6 }
104    
105    
106 greg 1.5 viewray(orig, direc, v, x, y) /* compute ray origin and direction */
107 greg 1.1 FVECT orig, direc;
108     register VIEW *v;
109     double x, y;
110     {
111 greg 1.12 double d, z;
112    
113 greg 1.5 x += v->hoff - 0.5;
114     y += v->voff - 0.5;
115 greg 1.1
116 greg 1.12 switch(v->type) {
117     case VT_PAR: /* parallel view */
118 greg 1.5 orig[0] = v->vp[0] + x*v->hvec[0] + y*v->vvec[0];
119     orig[1] = v->vp[1] + x*v->hvec[1] + y*v->vvec[1];
120     orig[2] = v->vp[2] + x*v->hvec[2] + y*v->vvec[2];
121 greg 1.1 VCOPY(direc, v->vdir);
122 greg 1.12 return(0);
123     case VT_PER: /* perspective view */
124 greg 1.1 VCOPY(orig, v->vp);
125 greg 1.5 direc[0] = v->vdir[0] + x*v->hvec[0] + y*v->vvec[0];
126     direc[1] = v->vdir[1] + x*v->hvec[1] + y*v->vvec[1];
127     direc[2] = v->vdir[2] + x*v->hvec[2] + y*v->vvec[2];
128 greg 1.1 normalize(direc);
129 greg 1.12 return(0);
130     case VT_HEM: /* hemispherical fisheye */
131 greg 1.13 z = 1.0 - x*x*v->hn2 - y*y*v->vn2;
132 greg 1.12 if (z < 0.0)
133     return(-1);
134     z = sqrt(z);
135     VCOPY(orig, v->vp);
136     direc[0] = z*v->vdir[0] + x*v->hvec[0] + y*v->vvec[0];
137     direc[1] = z*v->vdir[1] + x*v->hvec[1] + y*v->vvec[1];
138     direc[2] = z*v->vdir[2] + x*v->hvec[2] + y*v->vvec[2];
139     return(0);
140     case VT_ANG: /* angular fisheye */
141     x *= v->horiz/180.0;
142     y *= v->vert/180.0;
143     d = x*x + y*y;
144     if (d > 1.0)
145     return(-1);
146     VCOPY(orig, v->vp);
147     if (d <= FTINY) {
148     VCOPY(direc, v->vdir);
149     return(0);
150     }
151     d = sqrt(d);
152     z = cos(PI*d);
153     d = sqrt(1 - z*z)/d;
154     x *= d;
155     y *= d;
156     direc[0] = z*v->vdir[0] + x*v->hvec[0] + y*v->vvec[0];
157     direc[1] = z*v->vdir[1] + x*v->hvec[1] + y*v->vvec[1];
158     direc[2] = z*v->vdir[2] + x*v->hvec[2] + y*v->vvec[2];
159     return(0);
160 greg 1.1 }
161 greg 1.12 return(-1);
162 greg 1.1 }
163    
164    
165 greg 1.5 viewpixel(xp, yp, zp, v, p) /* find image location for point */
166 greg 1.3 double *xp, *yp, *zp;
167     register VIEW *v;
168     FVECT p;
169     {
170     double d;
171     FVECT disp;
172 greg 1.5
173 greg 1.3 disp[0] = p[0] - v->vp[0];
174     disp[1] = p[1] - v->vp[1];
175     disp[2] = p[2] - v->vp[2];
176    
177 greg 1.12 switch (v->type) {
178     case VT_PAR: /* parallel view */
179 greg 1.3 if (zp != NULL)
180     *zp = DOT(disp,v->vdir);
181 greg 1.13 break;
182 greg 1.12 case VT_PER: /* perspective view */
183 greg 1.11 d = DOT(disp,v->vdir);
184 greg 1.3 if (zp != NULL) {
185     *zp = sqrt(DOT(disp,disp));
186     if (d < 0.0)
187     *zp = -*zp;
188     }
189 greg 1.11 if (d < 0.0) /* fold pyramid */
190     d = -d;
191     if (d > FTINY) {
192     d = 1.0/d;
193     disp[0] *= d;
194     disp[1] *= d;
195     disp[2] *= d;
196     }
197 greg 1.13 break;
198 greg 1.12 case VT_HEM: /* hemispherical fisheye */
199     d = normalize(disp);
200     if (zp != NULL) {
201     if (DOT(disp,v->vdir) < 0.0)
202     *zp = -d;
203     else
204     *zp = d;
205     }
206 greg 1.13 break;
207 greg 1.12 case VT_ANG: /* angular fisheye */
208     d = normalize(disp);
209     if (zp != NULL)
210     *zp = d;
211     *xp = 0.5 - v->hoff;
212     *yp = 0.5 - v->voff;
213     d = DOT(disp,v->vdir);
214     if (d >= 1.0-FTINY)
215     return;
216     if (d <= -(1.0-FTINY)) {
217     *xp += 180.0/v->horiz;
218     *yp += 180.0/v->vert;
219     return;
220     }
221     d = acos(d)/PI / sqrt(1.0 - d*d);
222     *xp += DOT(disp,v->hvec)*d*180.0/v->horiz;
223     *yp += DOT(disp,v->vvec)*d*180.0/v->vert;
224     return;
225 greg 1.3 }
226 greg 1.13 *xp = DOT(disp,v->hvec)/v->hn2 + 0.5 - v->hoff;
227     *yp = DOT(disp,v->vvec)/v->vn2 + 0.5 - v->voff;
228 greg 1.3 }
229    
230    
231 greg 1.5 int
232     getviewopt(v, ac, av) /* process view argument */
233     register VIEW *v;
234     int ac;
235     register char *av[];
236     {
237 greg 1.16 #define check(c,l) if ((av[0][c]&&av[0][c]!=' ') || \
238     badarg(ac-1,av+1,l)) return(-1)
239 greg 1.5 extern double atof();
240    
241 greg 1.9 if (ac <= 0 || av[0][0] != '-' || av[0][1] != 'v')
242 greg 1.5 return(-1);
243     switch (av[0][2]) {
244     case 't': /* type */
245     if (!av[0][3] || av[0][3]==' ')
246     return(-1);
247 greg 1.16 check(4,"");
248 greg 1.5 v->type = av[0][3];
249     return(0);
250     case 'p': /* point */
251 greg 1.16 check(3,"fff");
252 greg 1.5 v->vp[0] = atof(av[1]);
253     v->vp[1] = atof(av[2]);
254     v->vp[2] = atof(av[3]);
255     return(3);
256     case 'd': /* direction */
257 greg 1.16 check(3,"fff");
258 greg 1.5 v->vdir[0] = atof(av[1]);
259     v->vdir[1] = atof(av[2]);
260     v->vdir[2] = atof(av[3]);
261     return(3);
262     case 'u': /* up */
263 greg 1.16 check(3,"fff");
264 greg 1.5 v->vup[0] = atof(av[1]);
265     v->vup[1] = atof(av[2]);
266     v->vup[2] = atof(av[3]);
267     return(3);
268     case 'h': /* horizontal size */
269 greg 1.16 check(3,"f");
270 greg 1.5 v->horiz = atof(av[1]);
271     return(1);
272     case 'v': /* vertical size */
273 greg 1.16 check(3,"f");
274 greg 1.5 v->vert = atof(av[1]);
275     return(1);
276     case 's': /* shift */
277 greg 1.16 check(3,"f");
278 greg 1.5 v->hoff = atof(av[1]);
279     return(1);
280     case 'l': /* lift */
281 greg 1.16 check(3,"f");
282 greg 1.5 v->voff = atof(av[1]);
283     return(1);
284     default:
285     return(-1);
286     }
287     #undef check
288     }
289    
290    
291     int
292     sscanview(vp, s) /* get view parameters from string */
293     VIEW *vp;
294 greg 1.1 register char *s;
295     {
296 greg 1.5 int ac;
297     char *av[4];
298     int na;
299     int nvopts = 0;
300    
301     while (*s == ' ')
302     s++;
303 greg 1.9 while (*s) {
304 greg 1.5 ac = 0;
305     do {
306     av[ac++] = s;
307     while (*s && *s != ' ')
308     s++;
309     while (*s == ' ')
310     s++;
311     } while (*s && ac < 4);
312     if ((na = getviewopt(vp, ac, av)) >= 0) {
313     if (na+1 < ac)
314     s = av[na+1];
315     nvopts++;
316 greg 1.9 } else if (ac > 1)
317     s = av[1];
318     }
319 greg 1.5 return(nvopts);
320 greg 1.1 }
321    
322    
323     fprintview(vp, fp) /* write out view parameters */
324     register VIEW *vp;
325     FILE *fp;
326     {
327     fprintf(fp, " -vt%c", vp->type);
328     fprintf(fp, " -vp %.6g %.6g %.6g", vp->vp[0], vp->vp[1], vp->vp[2]);
329     fprintf(fp, " -vd %.6g %.6g %.6g", vp->vdir[0], vp->vdir[1], vp->vdir[2]);
330     fprintf(fp, " -vu %.6g %.6g %.6g", vp->vup[0], vp->vup[1], vp->vup[2]);
331     fprintf(fp, " -vh %.6g -vv %.6g", vp->horiz, vp->vert);
332 greg 1.9 fprintf(fp, " -vs %.6g -vl %.6g", vp->hoff, vp->voff);
333 greg 1.1 }
334    
335    
336 greg 1.3 static char *altname[] = {NULL,"rpict","rview","pinterp",VIEWSTR,NULL};
337 greg 1.1
338 greg 1.15 struct myview {
339     VIEW *hv;
340     int ok;
341     };
342 greg 1.1
343 greg 1.15
344 greg 1.1 static
345 greg 1.15 gethview(s, v) /* get view from header */
346 greg 1.1 char *s;
347 greg 1.15 register struct myview *v;
348 greg 1.1 {
349     register char **an;
350    
351     for (an = altname; *an != NULL; an++)
352     if (!strncmp(*an, s, strlen(*an))) {
353 greg 1.15 if (sscanview(v->hv, s+strlen(*an)) > 0)
354     v->ok++;
355 greg 1.1 return;
356     }
357     }
358    
359    
360     int
361 greg 1.8 viewfile(fname, vp, xp, yp) /* get view from file */
362 greg 1.1 char *fname;
363     VIEW *vp;
364 greg 1.8 int *xp, *yp;
365 greg 1.1 {
366     extern char *progname;
367 greg 1.15 struct myview mvs;
368 greg 1.1 FILE *fp;
369    
370     if ((fp = fopen(fname, "r")) == NULL)
371     return(-1);
372    
373     altname[0] = progname;
374 greg 1.15 mvs.hv = vp;
375     mvs.ok = 0;
376 greg 1.1
377 greg 1.15 getheader(fp, gethview, &mvs);
378 greg 1.8
379     if (xp != NULL && yp != NULL
380     && fgetresolu(xp, yp, fp) == -1)
381 greg 1.15 mvs.ok = 0;
382 greg 1.1
383     fclose(fp);
384    
385 greg 1.15 return(mvs.ok);
386 greg 1.1 }