--- ray/src/common/image.c 1994/12/21 09:07:19 2.8 +++ ray/src/common/image.c 1999/02/26 12:24:07 2.15 @@ -1,4 +1,4 @@ -/* Copyright (c) 1994 Regents of the University of California */ +/* Copyright (c) 1996 Regents of the University of California */ #ifndef lint static char SCCSid[] = "$SunId$ LBL"; @@ -6,8 +6,6 @@ static char SCCSid[] = "$SunId$ LBL"; /* * image.c - routines for image generation. - * - * 10/17/85 */ #include "standard.h" @@ -18,6 +16,10 @@ static char SCCSid[] = "$SunId$ LBL"; #include "paths.h" +#define FEQ(x,y) (fabs((x)-(y)) <= FTINY) +#define VEQ(v,w) (FEQ((v)[0],(w)[0]) && FEQ((v)[1],(w)[1]) \ + && FEQ((v)[2],(w)[2])) + VIEW stdview = STDVIEW; /* default view parameters */ @@ -28,8 +30,7 @@ register VIEW *v; static char ill_horiz[] = "illegal horizontal view size"; static char ill_vert[] = "illegal vertical view size"; - if (v->vfore < -FTINY || v->vaft < -FTINY || - (v->vaft > FTINY && v->vaft <= v->vfore)) + if (v->vaft < -FTINY || (v->vaft > FTINY && v->vaft <= v->vfore)) return("illegal fore/aft clipping plane"); if (normalize(v->vdir) == 0.0) /* normalize direction */ @@ -63,13 +64,21 @@ register VIEW *v; v->hn2 = 2.0 * tan(v->horiz*(PI/180.0/2.0)); v->vn2 = 2.0 * tan(v->vert*(PI/180.0/2.0)); break; + case VT_CYL: /* cylindrical panorama */ + if (v->horiz > 360.0+FTINY) + return(ill_horiz); + if (v->vert >= 180.0-FTINY) + return(ill_vert); + v->hn2 = v->horiz * (PI/180.0); + v->vn2 = 2.0 * tan(v->vert*(PI/180.0/2.0)); + break; case VT_ANG: /* angular fisheye */ if (v->horiz > 360.0+FTINY) return(ill_horiz); if (v->vert > 360.0+FTINY) return(ill_vert); - v->hn2 = v->horiz / 90.0; - v->vn2 = v->vert / 90.0; + v->hn2 = v->horiz * (PI/180.0); + v->vn2 = v->vert * (PI/180.0); break; case VT_HEM: /* hemispherical fisheye */ if (v->horiz > 180.0+FTINY) @@ -83,9 +92,11 @@ register VIEW *v; return("unknown view type"); } if (v->type != VT_ANG) { - v->hvec[0] *= v->hn2; - v->hvec[1] *= v->hn2; - v->hvec[2] *= v->hn2; + if (v->type != VT_CYL) { + v->hvec[0] *= v->hn2; + v->hvec[1] *= v->hn2; + v->hvec[2] *= v->hn2; + } v->vvec[0] *= v->vn2; v->vvec[1] *= v->vn2; v->vvec[2] *= v->vn2; @@ -153,6 +164,18 @@ double x, y; orig[1] = v->vp[1] + v->vfore*direc[1]; orig[2] = v->vp[2] + v->vfore*direc[2]; return(v->vaft > FTINY ? v->vaft - v->vfore : 0.0); + case VT_CYL: /* cylindrical panorama */ + d = x * v->horiz * (PI/180.0); + z = cos(d); + x = sin(d); + direc[0] = z*v->vdir[0] + x*v->hvec[0] + y*v->vvec[0]; + direc[1] = z*v->vdir[1] + x*v->hvec[1] + y*v->vvec[1]; + direc[2] = z*v->vdir[2] + x*v->hvec[2] + y*v->vvec[2]; + orig[0] = v->vp[0] + v->vfore*direc[0]; + orig[1] = v->vp[1] + v->vfore*direc[1]; + orig[2] = v->vp[2] + v->vfore*direc[2]; + d = normalize(direc); + return(v->vaft > FTINY ? (v->vaft - v->vfore)*d : 0.0); case VT_ANG: /* angular fisheye */ x *= v->horiz/180.0; y *= v->vert/180.0; @@ -181,7 +204,7 @@ FVECT ip; register VIEW *v; FVECT p; { - double d; + double d, d2; FVECT disp; disp[0] = p[0] - v->vp[0]; @@ -194,7 +217,7 @@ FVECT p; break; case VT_PER: /* perspective view */ d = DOT(disp,v->vdir); - ip[2] = sqrt(DOT(disp,disp)); + ip[2] = VLEN(disp); if (d < 0.0) { /* fold pyramid */ ip[2] = -ip[2]; d = -d; @@ -215,6 +238,15 @@ FVECT p; ip[2] = d; ip[2] -= v->vfore; break; + case VT_CYL: /* cylindrical panorama */ + d = DOT(disp,v->hvec); + d2 = DOT(disp,v->vdir); + ip[0] = 180.0/PI * atan2(d,d2) / v->horiz + 0.5 - v->hoff; + d = 1.0/sqrt(d*d + d2*d2); + ip[1] = DOT(disp,v->vvec)*d/v->vn2 + 0.5 - v->voff; + ip[2] = VLEN(disp); + ip[2] *= (1.0 - v->vfore*d); + return; case VT_ANG: /* angular fisheye */ ip[0] = 0.5 - v->hoff; ip[1] = 0.5 - v->voff; @@ -224,7 +256,6 @@ FVECT p; return; if (d <= -(1.0-FTINY)) { ip[0] += 180.0/v->horiz; - ip[1] += 180.0/v->vert; return; } d = acos(d)/PI / sqrt(1.0 - d*d); @@ -361,7 +392,7 @@ register char *s; int nvopts = 0; if (*s != '-') - s = sskip(s); + s = sskip2(s,1); while (*s) { ac = 0; do { @@ -396,6 +427,60 @@ FILE *fp; } +char * +viewopt(vp) /* translate to minimal view string */ +register VIEW *vp; +{ + static char vwstr[128]; + register char *cp = vwstr; + + if (vp->type != stdview.type) { + sprintf(cp, " -vt%c", vp->type); + cp += strlen(cp); + } + if (!VEQ(vp->vp,stdview.vp)) { + sprintf(cp, " -vp %.6g %.6g %.6g", + vp->vp[0], vp->vp[1], vp->vp[2]); + cp += strlen(cp); + } + if (!VEQ(vp->vdir,stdview.vdir)) { + sprintf(cp, " -vd %.6g %.6g %.6g", + vp->vdir[0], vp->vdir[1], vp->vdir[2]); + cp += strlen(cp); + } + if (!VEQ(vp->vup,stdview.vup)) { + sprintf(cp, " -vu %.6g %.6g %.6g", + vp->vup[0], vp->vup[1], vp->vup[2]); + cp += strlen(cp); + } + if (!FEQ(vp->horiz,stdview.horiz)) { + sprintf(cp, " -vh %.6g", vp->horiz); + cp += strlen(cp); + } + if (!FEQ(vp->vert,stdview.vert)) { + sprintf(cp, " -vv %.6g", vp->vert); + cp += strlen(cp); + } + if (!FEQ(vp->vfore,stdview.vfore)) { + sprintf(cp, " -vo %.6g", vp->vfore); + cp += strlen(cp); + } + if (!FEQ(vp->vaft,stdview.vaft)) { + sprintf(cp, " -va %.6g", vp->vaft); + cp += strlen(cp); + } + if (!FEQ(vp->hoff,stdview.hoff)) { + sprintf(cp, " -vs %.6g", vp->hoff); + cp += strlen(cp); + } + if (!FEQ(vp->voff,stdview.voff)) { + sprintf(cp, " -vl %.6g", vp->voff); + cp += strlen(cp); + } + return(vwstr); +} + + int isview(s) /* is this a view string? */ char *s; @@ -431,13 +516,14 @@ struct myview { }; -static +static int gethview(s, v) /* get view from header */ char *s; register struct myview *v; { if (isview(s) && sscanview(v->hv, s) > 0) v->ok++; + return(0); }