static void zoomview( /* zoom in or out around (dx,dy) */ int pct, int dx, int dy ) { double h, v; if ((pct == 100) | (pct <= 0)) return; copylastv("zooming"); h = (dx+.5)/hres - 0.5; v = (dy+.5)/vres - 0.5; h *= (1. - 100./pct); v *= (1. - 100./pct); thisview.vdir[0] += h*thisview.hvec[0] + v*thisview.vvec[0]; thisview.vdir[1] += h*thisview.hvec[1] + v*thisview.vvec[1]; thisview.vdir[2] += h*thisview.hvec[2] + v*thisview.vvec[2]; thisview.horiz = 2.*180./PI * atan( 100./pct * tan(PI/180./2.*thisview.horiz) ); thisview.vert = 2.*180./PI * atan( 100./pct * tan(PI/180./2.*thisview.vert) ); setview(&thisview); dev_view(&thisview); }
static void resizewindow( /* resize window */ register XConfigureEvent *ersz ) { static char resizing[] = "resizing window"; double wa, va; glViewport(0, 0, hres=ersz->width, vres=ersz->height); if (hres > maxhres) maxhres = hres; if (vres > maxvres) maxvres = vres; if (no_render) return; wa = (vres*pheight)/(hres*pwidth); va = viewaspect(&thisview); if (va > wa+.05) { copylastv(resizing); thisview.vert = 2.*180./PI * atan( tan(PI/180./2. * thisview.horiz) * wa ); } else if (va < wa-.05) { copylastv(resizing); thisview.horiz = 2.*180./PI * atan( tan(PI/180./2. * thisview.vert) / wa ); } else return; setview(&thisview); dev_view(&thisview); }
static int getkey( /* get input key */ register XKeyPressedEvent *ekey ) { int n; char buf[8]; n = XLookupString(ekey, buf, sizeof(buf), NULL, NULL); if (n != 1) return(1); switch (buf[0]) { case 'h': /* turn on height motion lock */ headlocked = 1; break; case 'H': /* turn off height motion lock */ headlocked = 0; break; case 'l': /* retrieve last (premouse) view */ if (lastview.type) { VIEW vtmp; vtmp = thisview; dev_view(&lastview); lastview = vtmp; } else XBell(ourdisplay, 0); break; case 'n': /* move to next standard view */ gotoview(currentview+1); break; case 'p': /* move to last standard view */ gotoview(currentview-1); break; case '+': /* zoom in */ zoomview(100+ZOOMPCT, ekey->x, vres-1-ekey->y); break; case '-': /* zoom out */ zoomview(100-ZOOMPCT, ekey->x, vres-1-ekey->y); break; case 'v': /* spit current view to stdout */ fputs(VIEWSTR, stdout); fprintview(&thisview, stdout); fputc('\n', stdout); break; case 'V': /* append view to rad file */ appendview(NULL, &thisview); break; case 'q': /* quit the program */ return(0); default: XBell(ourdisplay, 0); break; } return(1); }
static void new_view( /* change view parameters */ register VIEW *v ) { static VIEW viewhist[VIEWHISTLEN]; static unsigned nhist; VIEW *dv; int i, res[2]; int16 *slist; char *err; /* restore previous view? */ if (v == NULL) { if (nhist > 1) /* get one before last setting */ nhist--; else /* else go to end of list */ while (nhist < VIEWHISTLEN && viewhist[nhist].type) nhist++; v = viewhist + ((nhist-1)%VIEWHISTLEN); } else again: if ((err = setview(v)) != NULL) { error(COMMAND, err); return; } if (!dev_view(v)) /* notify display driver */ goto again; if (v->type == VT_PAR) { error(COMMAND, "cannot handle parallel views"); return; } beam_init(odev.firstuse); /* compute new beam set */ for (i = 0; (dv = dev_auxview(i, res)) != NULL; i++) { if ((slist = beam_view(dv, res[0], res[1])) == NULL) { if (!nhist) { error(COMMAND, "invalid starting view"); return; } *v = *(viewhist + ((nhist-1)%VIEWHISTLEN)); goto again; /* XXX overloading dev_section()? */ } DCHECK(*slist < 0, WARNING, "no visible sections in new_view"); for ( ; *slist >= 0; slist++) dev_section(hdgfn[*slist], hdpfn[*slist]); } dev_section(NULL,NULL); /* end section list */ dev_flush(); /* update display */ /* update server */ imm_mode = beam_sync(odev.firstuse) > 0; /* record new view */ if (v < viewhist || v >= viewhist+VIEWHISTLEN) { *(viewhist + (nhist%VIEWHISTLEN)) = *v; nhist++; } }
static void gotoview( /* go to specified view number */ int vwnum ) { if (vwnum < 0) for (vwnum = currentview; vwl[vwnum+1].v != NULL; vwnum++) ; else if (vwnum >= MAXVIEW || vwl[vwnum].v == NULL) vwnum = 0; copylastv("standard view"); dev_view(vwl[currentview=vwnum].v); }
static int moveview( /* move our view */ int dx, int dy, int mov, int orb ) { VIEW nv; FVECT odir, v1; double d; int li; /* start with old view */ nv = odev.v; /* change view direction */ if (mov | orb) { if ((li = qtFindLeaf(dx, dy)) < 0) return(0); /* not on window */ VSUM(odir, qtL.wp[li], nv.vp, -1.); } else { if (viewray(nv.vp, nv.vdir, &odev.v, (dx+.5)/odev.hres, (dy+.5)/odev.vres) < -FTINY) return(0); /* outside view */ } if (orb && mov) { /* orbit left/right */ spinvector(odir, odir, nv.vup, d=MOVDEG*PI/180.*mov); VSUM(nv.vp, qtL.wp[li], odir, -1.); spinvector(nv.vdir, nv.vdir, nv.vup, d); } else if (orb) { /* orbit up/down */ if (geodesic(odir, odir, nv.vup, d=MOVDEG*PI/180.*orb, GEOD_RAD) == 0.0) return(0); VSUM(nv.vp, qtL.wp[li], odir, -1.); geodesic(nv.vdir, nv.vdir, nv.vup, d, GEOD_RAD); } else if (mov) { /* move forward/backward */ d = MOVPCT/100. * mov; VSUM(nv.vp, nv.vp, odir, d); } if (!mov ^ !orb && headlocked) { /* restore head height */ VSUM(v1, odev.v.vp, nv.vp, -1.); d = DOT(v1, odev.v.vup); VSUM(nv.vp, nv.vp, odev.v.vup, d); } if (setview(&nv) != NULL) return(0); /* illegal view */ dev_view(&nv); inpresflags |= DFL(DC_SETVIEW); return(1); }
static int moveview( /* move our view */ int dx, int dy, int mov, int orb ) { VIEW nv; FVECT odir, v1, wp; double d; /* start with old view */ nv = thisview; /* change view direction */ if ((d = viewray(v1, odir, &thisview, (dx+.5)/hres, (dy+.5)/vres)) < -FTINY) return(0); /* outside view */ if (mov | orb) { if (!getintersect(wp, v1, odir, d)) return(0); VSUM(odir, wp, nv.vp, -1.); } else VCOPY(nv.vdir, odir); if (orb && mov) { /* orbit left/right */ spinvector(odir, odir, nv.vup, d=MOVDEG*PI/180.*mov); VSUM(nv.vp, wp, odir, -1.); spinvector(nv.vdir, nv.vdir, nv.vup, d); } else if (orb) { /* orbit up/down */ if (geodesic(odir, odir, nv.vup, d=MOVDEG*PI/180.*orb, GEOD_RAD) == 0.0) return(0); VSUM(nv.vp, wp, odir, -1.); geodesic(nv.vdir, nv.vdir, nv.vup, d, GEOD_RAD); } else if (mov) { /* move forward/backward */ d = MOVPCT/100. * mov; VSUM(nv.vp, nv.vp, odir, d); } if (!mov ^ !orb && headlocked) { /* restore head height */ VSUM(v1, thisview.vp, nv.vp, -1.); d = DOT(v1, thisview.vup); VSUM(nv.vp, nv.vp, thisview.vup, d); } if (setview(&nv) != NULL) return(0); /* illegal view */ dev_view(&nv); return(1); }
int main( int argc, char *argv[] ) { char *viewsel = NULL; long vwintvl = 0; int i; progname = argv[0]; for (i = 1; i < argc && argv[i][0] == '-'; i++) switch (argv[i][1]) { case 'v': viewsel = argv[++i]; break; case 'w': nowarn = !nowarn; break; case 's': silent = !silent; break; case 'S': stereo = !stereo; break; case 'c': vwintvl = atoi(argv[++i]); break; case 'b': backvis = !backvis; break; default: goto userr; } if (i >= argc) goto userr; #ifdef NOSTEREO if (stereo) error(INTERNAL, "stereo not supported in this version"); #endif /* run rad and get views */ runrad(argc-i, argv+i); /* check view */ if (viewsel != NULL) { if (viewsel[0] == '-') { char *ve = viewsel; if (!sscanview(&thisview, viewsel) || (ve = setview(&thisview)) != NULL) { fprintf(stderr, "%s: bad view: %s\n", progname, ve); quit(1); } currentview = -1; } else if ((currentview = findvw(viewsel)) < 0) { fprintf(stderr, "%s: no such view: %s\n", progname, viewsel); quit(1); } } /* open GL */ dev_open(radfile = argv[i]); /* load octree or scene files */ if (octree != NULL) { displist = rgl_octlist(octree, NULL, NULL, NULL); startrtrace(octree); } else displist = rgl_filelist(nscenef, scene, NULL); /* set initial view */ dev_view(currentview < 0 ? &thisview : vwl[currentview].v); /* input/render loop */ while (dev_input(vwintvl)) ; /* all done */ quit(0); userr: fprintf(stderr, "Usage: %s [-w][-s][-b][-S][-v view] rfile [VAR=value]..\n", argv[0]); quit(1); return 1; /* pro forma return */ }