Back to index

radiance  4R0+20100331
Defines | Functions | Variables
rhdisp.c File Reference
#include <string.h>
#include <ctype.h>
#include "rterror.h"
#include "rholo.h"
#include "rhdisp.h"
#include "rhdriver.h"
#include "selcall.h"

Go to the source code of this file.

Defines

#define VIEWHISTLEN   4 /* number of remembered views */
#define FSIZDEF   0.125 /* default focus frame size */
#define fbufcnt(f)   ((f)->_cnt)
#define RDY_SRV   01
#define RDY_DEV   02
#define RDY_SIN   04

Functions

static int disp_wait (void)
static void add_holo (HDGRID *hdg, char *gfn, char *pfn)
static void disp_bundle (PACKHEAD *p)
static void new_view (register VIEW *v)
static void set_focus (char *args)
static int usr_input (void)
static void printview (void)
int main (int argc, char *argv[])
static void disp_bundle (register PACKHEAD *p)
int serv_result (void)
void serv_request (int type, int nbytes, char *p)
void eputs (register char *s)
void quit (int code)

Variables

static const char RCSid [] = "$Id: rhdisp.c,v 3.52 2008/03/11 02:21:47 greg Exp $"
HOLOhdlist [HDMAX+1]
char * hdgfn [HDMAX]
char * hdpfn [HDMAX]
char cmdlist [DC_NCMDS][8] = DC_INIT
int imm_mode = 0
int do_outside = 0
double eyesepdist = 1
char * progname
FILE * sstdin
FILE * sstdout

Define Documentation

#define fbufcnt (   f)    ((f)->_cnt)

Definition at line 30 of file rhdisp.c.

#define FSIZDEF   0.125 /* default focus frame size */

Definition at line 22 of file rhdisp.c.

#define RDY_DEV   02

Definition at line 58 of file rhdisp.c.

#define RDY_SIN   04

Definition at line 59 of file rhdisp.c.

#define RDY_SRV   01

Definition at line 57 of file rhdisp.c.

#define VIEWHISTLEN   4 /* number of remembered views */

Definition at line 18 of file rhdisp.c.


Function Documentation

static void add_holo ( HDGRID hdg,
char *  gfn,
char *  pfn 
) [static]

Definition at line 218 of file rhdisp.c.

{
       VIEW   nv;
       double d;
       register int  hd;

       for (hd = 0; hd < HDMAX && hdlist[hd] != NULL; hd++)
              ;
       if (hd >= HDMAX)
              error(INTERNAL, "too many holodeck sections in add_holo");
       hdlist[hd] = (HOLO *)malloc(sizeof(HOLO));
       if (hdlist[hd] == NULL)
              error(SYSTEM, "out of memory in add_holo");
       memcpy((void *)hdlist[hd], (void *)hdg, sizeof(HDGRID));
       hdcompgrid(hdlist[hd]);
       hdgfn[hd] = savestr(gfn);
       hdpfn[hd] = pfn && *pfn ? savestr(pfn) : (char *)NULL;
       if (hd)
              return;
                                   /* set initial viewpoint */
       nv = odev.v;
       VSUM(nv.vp, hdlist[0]->orig, hdlist[0]->xv[0], 0.5);
       VSUM(nv.vp, nv.vp, hdlist[0]->xv[1], 0.5);
       VSUM(nv.vp, nv.vp, hdlist[0]->xv[2], 0.5);
       fcross(nv.vdir, hdlist[0]->xv[1], hdlist[0]->xv[2]);
       VCOPY(nv.vup, hdlist[0]->xv[2]);
       if (do_outside) {
              normalize(nv.vdir);
              d = VLEN(hdlist[0]->xv[1]);
              d += VLEN(hdlist[0]->xv[2]);
              VSUM(nv.vp, nv.vp, nv.vdir, -d);
       }
       new_view(&nv);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void disp_bundle ( PACKHEAD p) [static]

Here is the caller graph for this function:

static void disp_bundle ( register PACKHEAD p) [static]

Definition at line 259 of file rhdisp.c.

{
       GCOORD gc[2];
       FVECT  ro, rd, wp;
       double d;
       register int  i;
                                   /* get beam coordinates */
       if ((p->hd < 0) | (p->hd >= HDMAX) || hdlist[p->hd] == NULL)
              error(INTERNAL, "bad holodeck number in disp_bundle");
       if (!hdbcoord(gc, hdlist[p->hd], p->bi))
              error(INTERNAL, "bad beam index in disp_bundle");
                                   /* display each ray */
       for (i = p->nr; i--; ) {
              hdray(ro, rd, hdlist[p->hd], gc, packra(p)[i].r);
              d = hddepth(hdlist[p->hd], packra(p)[i].d);
              if (d < .99*FHUGE) {
                     VSUM(wp, ro, rd, d); /* might be behind viewpoint */
                     dev_value(packra(p)[i].v, rd, wp);
              } else
                     dev_value(packra(p)[i].v, rd, NULL);
       }
#ifdef DEBUG
       if (imm_mode) nimmrays += p->nr;
       else naddrays += p->nr;
#endif
}

Here is the call graph for this function:

static int disp_wait ( void  ) [static]

Definition at line 168 of file rhdisp.c.

{
       fd_set readset, errset;
       int    flgs;
       int    n;
                            /* see if we can avoid select call */
       if (hdlist[0] == NULL)
              return(RDY_SRV);     /* initialize first */
       flgs = 0;            /* flag what's ready already */
       if (imm_mode || fbufcnt(stdin) > 0)
              flgs |= RDY_SRV;
       if (sstdin != NULL && fbufcnt(sstdin) > 0)
              flgs |= RDY_SIN;
       if (odev.inpready)
              flgs |= RDY_DEV;
       if (flgs)            /* got something? */
              return(flgs);
       if (dev_flush())     /* else flush output & check keyboard+mouse */
              return(RDY_DEV);
                            /* if nothing, we need to call select */
       FD_ZERO(&readset); FD_ZERO(&errset);
       FD_SET(0, &readset);
       FD_SET(0, &errset);
       FD_SET(odev.ifd, &readset);
       FD_SET(odev.ifd, &errset);
       n = odev.ifd+1;
       if (sstdin != NULL) {
              FD_SET(fileno(sstdin), &readset);
              FD_SET(fileno(sstdin), &errset);
              if (fileno(sstdin) >= n)
                     n = fileno(sstdin) + 1;
       }
       n = select(n, &readset, NULL, &errset, NULL);
       if (n < 0) {
              if (errno == EINTR)
                     return(0);
              error(SYSTEM, "select call failure in disp_wait");
       }
       if (FD_ISSET(0, &readset) || FD_ISSET(0, &errset))
              flgs |= RDY_SRV;
       if (FD_ISSET(odev.ifd, &readset) || FD_ISSET(odev.ifd, &errset))
              flgs |= RDY_DEV;
       if (sstdin != NULL && (FD_ISSET(fileno(sstdin), &readset) ||
                            FD_ISSET(fileno(sstdin), &errset)))
              flgs |= RDY_SIN;
       return(flgs);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void eputs ( register char *  s)

Definition at line 609 of file rhdisp.c.

{
       static int  midline = 0;

       if (!*s)
              return;
       if (!midline++) {    /* prepend line with program name */
              fputs(progname, stderr);
              fputs(": ", stderr);
       }
       fputs(s, stderr);
       if (s[strlen(s)-1] == '\n') {
              fflush(stderr);
              midline = 0;
       }
}
int main ( int  argc,
char *  argv[] 
)

Definition at line 71 of file rhdisp.c.

{
       int    rdy, inp, res = 0, pause = 0;

       progname = argv[0];
       if (argc < 3)
              error(USER, "bad command line arguments");
                                   /* open our device */
       dev_open(argv[1]);
                                   /* open server process i/o */
       sstdout = fdopen(atoi(argv[2]), "w");
       if (argc < 4 || (inp = atoi(argv[3])) < 0)
              sstdin = NULL;
       else
              sstdin = fdopen(inp, "r");
                                   /* set command error vector */
       erract[COMMAND].pf = eputs;
#ifdef DEBUG
       tmodesw = time(NULL);
#endif
                                   /* enter main loop */
       do {
              rdy = disp_wait();
              if (rdy & RDY_SRV) {        /* process server result */
                     res = serv_result();
                     if (pause && res != DS_SHUTDOWN) {
                            serv_request(DR_ATTEN, 0, NULL);
                            while ((res = serv_result()) != DS_ACKNOW &&
                                          res != DS_SHUTDOWN)
                                   ;
                     }
              }
              if (rdy & RDY_DEV) {        /* user input from driver */
                     inp = dev_input();
                     if (inp & DFL(DC_SETVIEW))
                            new_view(&odev.v);
                     else if (inp & DFL(DC_LASTVIEW))
                            new_view(NULL);
                     if (inp & DFL(DC_REDRAW))
                            imm_mode = beam_sync(1) > 0;
                     if (inp & DFL(DC_GETVIEW))
                            printview();
                     if (inp & DFL(DC_FOCUS))
                            set_focus(odev_args);
                     if (inp & DFL(DC_KILL)) {
                            serv_request(DR_KILL, 0, NULL);
                            pause = 0;
                     }
                     if (inp & DFL(DC_CLOBBER))
                            serv_request(DR_CLOBBER, 0, NULL);
                     if (inp & DFL(DC_RESTART)) {
                            serv_request(DR_RESTART, 0, NULL);
                            pause = 0;
                     }
                     if (inp & DFL(DC_RESUME)) {
                            serv_request(DR_NOOP, 0, NULL);
                            pause = 0;
                     }
                     if (inp & DFL(DC_PAUSE))
                            pause = 1;
                     if (inp & DFL(DC_QUIT))
                            serv_request(DR_SHUTDOWN, 0, NULL);
              }
              if (rdy & RDY_SIN && !imm_mode)    /* user input from sstdin */
                     switch (usr_input()) {
                     case DC_PAUSE:
                            pause = 1;
                            break;
                     case DC_RESUME:
                            serv_request(DR_NOOP, 0, NULL);
                            /* fall through */
                     case DC_KILL:
                     case DC_RESTART:
                            pause = 0;
                            break;
                     }
       } while (res != DS_SHUTDOWN);
#ifdef DEBUG
       if (timm && nimmrays)
              fprintf(stderr,
                     "%s: %.1f rays recalled/second (%ld rays total)\n",
                            progname, (double)nimmrays/timm, nimmrays);
       if (tadd && naddrays)
              fprintf(stderr,
                     "%s: %.1f rays calculated/second (%ld rays total)\n",
                            progname, (double)naddrays/tadd, naddrays);
#endif
                                   /* all done */
       quit(0);
       return 0; /* pro forma return */
}

Here is the call graph for this function:

static void new_view ( register VIEW v) [static]

Definition at line 290 of file rhdisp.c.

{
       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++;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void printview ( void  ) [static]

Definition at line 493 of file rhdisp.c.

{
       fputs(VIEWSTR, sstdout);
       fprintview(&odev.v, sstdout);
       fputc('\n', sstdout);
       fflush(sstdout);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void quit ( int  code)

Definition at line 630 of file rhdisp.c.

{
       if (code)
              exit(code);
       if (odev.v.type)
              dev_close();
       exit(0);
}

Here is the call graph for this function:

void serv_request ( int  type,
int  nbytes,
char *  p 
)

Definition at line 580 of file rhdisp.c.

{
       MSGHEAD       msg;
       int    m;
                            /* consistency checks */
       DCHECK(nbytes < 0 || nbytes > 0 & p == NULL,
                     CONSISTENCY, "bad buffer handed to serv_request");
                            /* get server's attention for big request */
       if (nbytes >= BIGREQSIZ-sizeof(MSGHEAD)) {
              serv_request(DR_ATTEN, 0, NULL);
              while ((m = serv_result()) != DS_ACKNOW)
                     if (m == DS_SHUTDOWN)       /* the bugger quit on us */
                            quit(0);
       }
       msg.type = type;     /* write and flush the message */
       msg.nbytes = nbytes;
       fwrite((char *)&msg, sizeof(MSGHEAD), 1, stdout);
       if (nbytes > 0)
              fwrite(p, 1, nbytes, stdout);
       if (fflush(stdout) < 0)
              error(SYSTEM, "write error in serv_request");
}

Here is the call graph for this function:

Here is the caller graph for this function:

int serv_result ( void  )

Definition at line 503 of file rhdisp.c.

{
       static char   *buf = NULL;
       static int    bufsiz = 0;
       MSGHEAD       msg;
                                   /* read message header */
       if (fread((char *)&msg, sizeof(MSGHEAD), 1, stdin) != 1)
              goto readerr;
       if (msg.nbytes > 0) {              /* get the message body */
              if (msg.nbytes > bufsiz) {
                     if (buf == NULL)
                            buf = (char *)malloc(bufsiz=msg.nbytes);
                     else
                            buf = (char *)realloc((void *)buf,
                                          bufsiz=msg.nbytes);
                     if (buf == NULL)
                            error(SYSTEM, "out of memory in serv_result");
              }
              if (fread(buf, 1, msg.nbytes, stdin) != msg.nbytes)
                     goto readerr;
       }
       switch (msg.type) {         /* process results */
       case DS_BUNDLE:
              if (msg.nbytes < sizeof(PACKHEAD) ||
                            msg.nbytes != packsiz(((PACKHEAD *)buf)->nr))
                     error(INTERNAL, "bad display packet from server");
              disp_bundle((PACKHEAD *)buf);
              break;
       case DS_ADDHOLO:
              if (msg.nbytes < sizeof(HDGRID)+2)
                     error(INTERNAL, "bad holodeck record from server");
              add_holo((HDGRID *)buf, buf+sizeof(HDGRID),
                     buf+sizeof(HDGRID)+strlen(buf+sizeof(HDGRID))+1);
              break;
       case DS_OUTSECT:
              do_outside = 1;
              goto noargs;
       case DS_EYESEP:
              if (msg.nbytes <= 1 || (eyesepdist = atof(buf)) <= FTINY)
                     error(INTERNAL, "bad eye separation from server");
              break;
       case DS_STARTIMM:
       case DS_ENDIMM:
              if (!(imm_mode = msg.type==DS_STARTIMM))
                     dev_flush();
#ifdef DEBUG
              {
                     time_t tnow = time(NULL);
                     if (msg.type==DS_STARTIMM) tadd += tnow - tmodesw;
                     else timm += tnow - tmodesw;
                     tmodesw = tnow;
              }
#endif
              goto noargs;
       case DS_ACKNOW:
       case DS_SHUTDOWN:
              goto noargs;
       default:
              error(INTERNAL, "unrecognized result from server process");
       }
       return(msg.type);           /* return message type */
noargs:
       if (msg.nbytes) {
              sprintf(errmsg, "unexpected body with server message %d",
                            msg.type);
              error(INTERNAL, errmsg);
       }
       return(msg.type);
readerr:
       if (feof(stdin))
              error(SYSTEM, "server process died");
       error(SYSTEM, "error reading from server process");
       return -1;  
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void set_focus ( char *  args) [static]

Definition at line 347 of file rhdisp.c.

{
       double hcent, vcent, hsiz, vsiz;
       VIEW   *dv, vwfocus;
       int    i, res[2];

       i = sscanf(args, "%lf %lf %lf %lf", &hcent, &vcent, &hsiz, &vsiz);
       if (i < 2 || hcent < 0 || hcent > 1 || vcent < 0 || vcent > 1) {
              beam_init(0);                      /* restore view */
              for (i = 0; (dv = dev_auxview(i, res)) != NULL; i++)
                     beam_view(dv, res[0], res[1]);
              beam_sync(0);                      /* update server */
              return;
       }
       if (i < 4 || hsiz <= hcent || hsiz > 1 || vsiz <= vcent || vsiz > 1)
              hsiz = vsiz = FSIZDEF;                    /* gave center only */
       else {
              hsiz -= hcent; hcent += 0.5*hsiz;  /* gave min and max */
              vsiz -= vcent; vcent += 0.5*vsiz;
       }
       beam_init(0);                             /* add basic views */
       for (i = 0; (dv = dev_auxview(i, res)) != NULL; i++)
              beam_view(dv, res[0]>>4, res[1]>>4);
       vwfocus = odev.v;                  /* add focus view */
       switch (odev.v.type) {
       case VT_PER:
              vwfocus.horiz = 2.*180./PI*atan(
                            hsiz * tan(PI/180./2.*odev.v.horiz) );
              vwfocus.vert = 2.*180./PI*atan(
                            vsiz * tan(PI/180./2.*odev.v.vert) );
              break;
       case VT_PAR:
       case VT_ANG:
              vwfocus.horiz = hsiz * odev.v.horiz;
              vwfocus.vert = vsiz * odev.v.vert;
              break;
       case VT_PLS:
              vwfocus.horiz = hsiz * sin((PI/180./2.)*odev.v.horiz) /
                            (1.0 + cos((PI/180./2.)*odev.v.horiz));
              vwfocus.horiz *= vwfocus.horiz;
              vwfocus.horiz = (2.*180./PI)*acos((1. - vwfocus.horiz) /
                                          (1. + vwfocus.horiz));
              vwfocus.vert = vsiz * sin((PI/180./2.)*odev.v.vert) /
                            (1.0 + cos((PI/180./2.)*odev.v.vert));
              vwfocus.vert *= vwfocus.vert;
              vwfocus.vert = (2.*180./PI)*acos((1. - vwfocus.vert) /
                                          (1. + vwfocus.vert));
              break;
       case VT_HEM:
              vwfocus.horiz = 2.*180./PI*asin(
                            hsiz * sin(PI/180./2.*odev.v.horiz) );
              vwfocus.vert = 2.*180./PI*asin(
                            vsiz * sin(PI/180./2.*odev.v.vert) );
              break;
       case VT_CYL:
              vwfocus.horiz = hsiz * odev.v.horiz;
              vwfocus.vert = 2.*180./PI*atan(
                            vsiz * tan(PI/180./2.*odev.v.vert) );
              break;
       default:
              error(INTERNAL, "bad view type in set_focus");
       }
       vwfocus.hoff = (odev.v.hoff + hcent - 0.5)/hsiz;
       vwfocus.voff = (odev.v.voff + vcent - 0.5)/vsiz;
       setview(&vwfocus);
       beam_view(&vwfocus, (int)(3*odev.hres*hsiz)+100,
                     (int)(3*odev.vres*vsiz)+100);
       beam_sync(0);                             /* update server */
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int usr_input ( void  ) [static]

Definition at line 421 of file rhdisp.c.

{
       VIEW   vparams;
       char   cmd[256];
       register char *args;
       register int  i;

       if (fgets(cmd, sizeof(cmd), sstdin) == NULL) {
              fclose(sstdin);
              sstdin = NULL;
              return(-1);
       }
       if (*cmd == '\n')
              return(DC_RESUME);
       for (args = cmd; *args && !isspace(*args); args++)
              ;
       while (isspace(*args))
              *args++ = '\0';
       if (*args && args[i=strlen(args)-1] == '\n')
              args[i] = '\0';
       for (i = 0; i < DC_NCMDS; i++)
              if (!strcmp(cmd, cmdlist[i]))
                     break;
       if (i >= DC_NCMDS) {
              dev_auxcom(cmd, args);
              return(-1);
       }
       switch (i) {
       case DC_SETVIEW:            /* set the view */
              vparams = odev.v;
              if (!sscanview(&vparams, args))
                     error(COMMAND, "missing view options");
              else
                     new_view(&vparams);
              break;
       case DC_GETVIEW:            /* print the current view */
              printview();
              break;
       case DC_LASTVIEW:           /* restore previous view */
              new_view(NULL);
              break;
       case DC_FOCUS:                     /* set focus frame */
              set_focus(args);
              break;
       case DC_PAUSE:                     /* pause the current calculation */
       case DC_RESUME:                    /* resume the calculation */
              /* handled in main() */
              break;
       case DC_REDRAW:                    /* redraw from server */
              imm_mode = beam_sync(1) > 0;
              dev_clear();
              break;
       case DC_KILL:               /* kill rtrace process(es) */
              serv_request(DR_KILL, 0, NULL);
              break;
       case DC_CLOBBER:            /* clobber holodeck */
              serv_request(DR_CLOBBER, 0, NULL);
              break;
       case DC_RESTART:            /* restart rtrace */
              serv_request(DR_RESTART, 0, NULL);
              break;
       case DC_QUIT:               /* quit request */
              serv_request(DR_SHUTDOWN, 0, NULL);
              break;
       default:
              error(CONSISTENCY, "bad command id in usr_input");
       }
       return(i);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

char cmdlist[DC_NCMDS][8] = DC_INIT

Definition at line 38 of file rhdisp.c.

int do_outside = 0

Definition at line 42 of file rhdisp.c.

double eyesepdist = 1

Definition at line 44 of file rhdisp.c.

char* hdgfn[HDMAX]

Definition at line 35 of file rhdisp.c.

Definition at line 33 of file rhdisp.c.

char* hdpfn[HDMAX]

Definition at line 36 of file rhdisp.c.

int imm_mode = 0

Definition at line 40 of file rhdisp.c.

char* progname

Definition at line 46 of file rhdisp.c.

const char RCSid[] = "$Id: rhdisp.c,v 3.52 2008/03/11 02:21:47 greg Exp $" [static]

Definition at line 2 of file rhdisp.c.

FILE* sstdin

Definition at line 48 of file rhdisp.c.

FILE * sstdout

Definition at line 48 of file rhdisp.c.