ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp.c
Revision: 3.12
Committed: Thu Dec 11 09:37:43 1997 UTC (26 years, 11 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.11: +39 -16 lines
Log Message:
added command for returning to previous view(s)
added check to dev_view() for illegal views
fixed bug in X11 driver on window resizing

File Contents

# Content
1 /* Copyright (c) 1997 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * Holodeck display process.
9 */
10
11 #include "rholo.h"
12 #include "rhdisp.h"
13 #include "rhdriver.h"
14 #include "selcall.h"
15 #include <ctype.h>
16
17 #ifndef VIEWHISTLEN
18 #define VIEWHISTLEN 2 /* number of remembered views */
19 #endif
20
21 HOLO *hdlist[HDMAX+1]; /* global holodeck list */
22
23 char cmdlist[DC_NCMDS][8] = DC_INIT;
24
25 int imm_mode = 0; /* bundles are being delivered immediately */
26
27 char *progname; /* global argv[0] */
28
29 FILE *sstdin, *sstdout; /* server's standard input and output */
30
31 #define RDY_SRV 01
32 #define RDY_DEV 02
33 #define RDY_SIN 04
34
35
36 main(argc, argv)
37 int argc;
38 char *argv[];
39 {
40 extern int eputs();
41 int rdy, inp, res = 0, pause = 0;
42
43 progname = argv[0];
44 if (argc < 3)
45 error(USER, "bad command line arguments");
46 /* open our device */
47 dev_open(argv[1]);
48 /* open server process i/o */
49 sstdout = fdopen(atoi(argv[2]), "w");
50 if (argc < 4 || (inp = atoi(argv[3])) < 0)
51 sstdin = NULL;
52 else
53 sstdin = fdopen(inp, "r");
54 /* set command error vector */
55 erract[COMMAND].pf = eputs;
56 /* enter main loop */
57 do {
58 rdy = disp_wait();
59 if (rdy & RDY_DEV) { /* user input from driver */
60 inp = dev_input();
61 if (inp & DEV_PUTVIEW)
62 printview();
63 if (inp & DEV_NEWVIEW)
64 new_view(&odev.v);
65 if (inp & DEV_LASTVIEW)
66 new_view(NULL);
67 if (inp & DEV_SHUTDOWN)
68 serv_request(DR_SHUTDOWN, 0, NULL);
69 if (inp & DEV_REDRAW)
70 imm_mode = beam_sync() > 0;
71 if (inp & DEV_WAIT)
72 pause = 1;
73 if (inp & DEV_RESUME) {
74 serv_request(DR_NOOP, 0, NULL);
75 pause = 0;
76 }
77 }
78 if (rdy & RDY_SIN) /* user input from sstdin */
79 switch (usr_input()) {
80 case DC_PAUSE:
81 pause = 1;
82 break;
83 case DC_RESUME:
84 serv_request(DR_NOOP, 0, NULL);
85 pause = 0;
86 break;
87 }
88 if (rdy & RDY_SRV) { /* process server result */
89 res = serv_result();
90 if (pause && res != DS_SHUTDOWN) {
91 serv_request(DR_ATTEN, 0, NULL);
92 while ((res = serv_result()) != DS_ACKNOW &&
93 res != DS_SHUTDOWN)
94 ;
95 }
96 }
97 } while (res != DS_SHUTDOWN);
98 /* all done */
99 quit(0);
100 }
101
102
103 int
104 disp_wait() /* wait for more input */
105 {
106 fd_set readset, errset;
107 int flgs;
108 int n;
109 register int i;
110 /* see if we can avoid select call */
111 if (imm_mode || stdin->_cnt > 0)
112 return(RDY_SRV);
113 if (sstdin != NULL && sstdin->_cnt > 0)
114 return(RDY_SIN);
115 if (dev_flush())
116 return(RDY_DEV);
117 /* make the call */
118 FD_ZERO(&readset); FD_ZERO(&errset);
119 FD_SET(0, &readset);
120 FD_SET(0, &errset);
121 FD_SET(odev.ifd, &readset);
122 FD_SET(odev.ifd, &errset);
123 n = odev.ifd+1;
124 if (sstdin != NULL) {
125 FD_SET(fileno(sstdin), &readset);
126 if (fileno(sstdin) >= n)
127 n = fileno(sstdin) + 1;
128 }
129 n = select(n, &readset, NULL, &errset, NULL);
130 if (n < 0) {
131 if (errno == EINTR)
132 return(0);
133 error(SYSTEM, "select call failure in disp_wait");
134 }
135 flgs = 0; /* flag what's ready */
136 if (FD_ISSET(0, &readset) || FD_ISSET(0, &errset))
137 flgs |= RDY_SRV;
138 if (FD_ISSET(odev.ifd, &readset) || FD_ISSET(odev.ifd, &errset))
139 flgs |= RDY_DEV;
140 if (sstdin != NULL && FD_ISSET(fileno(sstdin), &readset))
141 flgs |= RDY_SIN;
142 return(flgs);
143 }
144
145
146 add_holo(hdg) /* register a new holodeck section */
147 HDGRID *hdg;
148 {
149 VIEW nv;
150 register int hd;
151
152 for (hd = 0; hd < HDMAX && hdlist[hd] != NULL; hd++)
153 ;
154 if (hd >= HDMAX)
155 error(INTERNAL, "too many holodeck sections in add_holo");
156 hdlist[hd] = (HOLO *)malloc(sizeof(HOLO));
157 if (hdlist[hd] == NULL)
158 error(SYSTEM, "out of memory in add_holo");
159 bcopy((char *)hdg, (char *)hdlist[hd], sizeof(HDGRID));
160 hdcompgrid(hdlist[hd]);
161 if (hd)
162 return;
163 /* set initial viewpoint */
164 copystruct(&nv, &odev.v);
165 VSUM(nv.vp, hdlist[0]->orig, hdlist[0]->xv[0], 0.5);
166 VSUM(nv.vp, nv.vp, hdlist[0]->xv[1], 0.5);
167 VSUM(nv.vp, nv.vp, hdlist[0]->xv[2], 0.5);
168 fcross(nv.vdir, hdlist[0]->xv[1], hdlist[0]->xv[2]);
169 VCOPY(nv.vup, hdlist[0]->xv[2]);
170 new_view(&nv);
171 }
172
173
174 disp_bundle(p) /* display a ray bundle */
175 register PACKHEAD *p;
176 {
177 GCOORD gc[2];
178 FVECT ro, rd, wp;
179 double d;
180 register int i;
181 /* get beam coordinates */
182 if (p->hd < 0 | p->hd >= HDMAX || hdlist[p->hd] == NULL)
183 error(INTERNAL, "bad holodeck number in disp_bundle");
184 if (!hdbcoord(gc, hdlist[p->hd], p->bi))
185 error(INTERNAL, "bad beam index in disp_bundle");
186 /* display each ray */
187 for (i = p->nr; i--; ) {
188 hdray(ro, rd, hdlist[p->hd], gc, packra(p)[i].r);
189 d = hddepth(hdlist[p->hd], packra(p)[i].d);
190 VSUM(wp, ro, rd, d); /* might be behind viewpoint */
191 dev_value(packra(p)[i].v, wp, rd);
192 }
193 }
194
195
196 new_view(v) /* change view parameters */
197 register VIEW *v;
198 {
199 static VIEW viewhist[VIEWHISTLEN];
200 static unsigned nhist;
201 char *err;
202 /* restore previous view? */
203 if (v == NULL) {
204 if (nhist < 2) {
205 error(COMMAND, "no previous view");
206 return;
207 }
208 nhist--; /* get one before last setting */
209 v = viewhist + ((nhist-1)%VIEWHISTLEN);
210 } else if ((err = setview(v)) != NULL) {
211 error(COMMAND, err);
212 return;
213 }
214 again:
215 if (v->type == VT_PAR) {
216 error(COMMAND, "cannot handle parallel views");
217 return;
218 }
219 if (!dev_view(v)) /* update display driver */
220 goto again;
221 dev_flush(); /* update screen */
222 if (!beam_view(v)) /* update beam list */
223 goto again;
224 /* record new view */
225 if (v < viewhist || v >= viewhist+VIEWHISTLEN) {
226 copystruct(viewhist + (nhist%VIEWHISTLEN), v);
227 nhist++;
228 }
229 }
230
231
232 int
233 usr_input() /* get user input and process it */
234 {
235 VIEW vparams;
236 char cmd[128];
237 register char *args;
238 register int i;
239
240 if (fgets(cmd, sizeof(cmd), sstdin) == NULL)
241 return(DC_QUIT);
242 for (args = cmd; *args && !isspace(*args); args++)
243 ;
244 while (isspace(*args))
245 *args++ = '\0';
246 if (!*cmd)
247 return(DC_RESUME);
248 if (*args && args[i=strlen(args)-1] == '\n')
249 args[i] = '\0';
250 for (i = 0; i < DC_NCMDS; i++)
251 if (!strcmp(cmd, cmdlist[i]))
252 break;
253 if (i >= DC_NCMDS) {
254 sprintf(errmsg, "unknown command: %s", cmd);
255 error(COMMAND, errmsg);
256 return(-1);
257 }
258 switch (i) {
259 case DC_SETVIEW: /* set the view */
260 copystruct(&vparams, &odev.v);
261 if (!sscanview(&vparams, args))
262 error(COMMAND, "missing view options");
263 else
264 new_view(&vparams);
265 break;
266 case DC_GETVIEW: /* print the current view */
267 printview();
268 break;
269 case DC_LASTVIEW: /* restore previous view */
270 new_view(NULL);
271 break;
272 case DC_PAUSE: /* pause the current calculation */
273 case DC_RESUME: /* resume the calculation */
274 /* handled in main() */
275 break;
276 case DC_QUIT: /* quit request */
277 serv_request(DR_SHUTDOWN, 0, NULL);
278 break;
279 default:
280 error(CONSISTENCY, "bad command id in usr_input");
281 }
282 return(i);
283 }
284
285
286 printview() /* print our current view to server stdout */
287 {
288 fputs(VIEWSTR, sstdout);
289 fprintview(&odev.v, sstdout);
290 fputc('\n', sstdout);
291 fflush(sstdout);
292 }
293
294
295 int
296 serv_result() /* get next server result and process it */
297 {
298 static char *buf = NULL;
299 static int bufsiz = 0;
300 MSGHEAD msg;
301 int n;
302 /* read message header */
303 if (fread((char *)&msg, sizeof(MSGHEAD), 1, stdin) != 1)
304 goto readerr;
305 if (msg.nbytes > 0) { /* get the message body */
306 if (msg.nbytes > bufsiz) {
307 if (buf == NULL)
308 buf = (char *)malloc(bufsiz=msg.nbytes);
309 else
310 buf = (char *)realloc(buf, bufsiz=msg.nbytes);
311 if (buf == NULL)
312 error(SYSTEM, "out of memory in serv_result");
313 }
314 if (fread(buf, 1, msg.nbytes, stdin) != msg.nbytes)
315 goto readerr;
316 }
317 switch (msg.type) { /* process results */
318 case DS_BUNDLE:
319 if (msg.nbytes < sizeof(PACKHEAD) ||
320 msg.nbytes != packsiz(((PACKHEAD *)buf)->nr))
321 error(INTERNAL, "bad display packet from server");
322 disp_bundle((PACKHEAD *)buf);
323 break;
324 case DS_ADDHOLO:
325 if (msg.nbytes != sizeof(HDGRID))
326 error(INTERNAL, "bad holodeck record from server");
327 add_holo((HDGRID *)buf);
328 break;
329 case DS_STARTIMM:
330 case DS_ENDIMM:
331 imm_mode = msg.type==DS_STARTIMM;
332 if (msg.type == DS_ENDIMM)
333 dev_flush(); /* update display NOW */
334 /* fall through */
335 case DS_ACKNOW:
336 case DS_SHUTDOWN:
337 if (msg.nbytes) {
338 sprintf(errmsg,
339 "unexpected body with server message %d",
340 msg.type);
341 error(INTERNAL, errmsg);
342 }
343 break;
344 default:
345 error(INTERNAL, "unrecognized result from server process");
346 }
347 return(msg.type); /* return message type */
348 readerr:
349 if (feof(stdin))
350 error(SYSTEM, "server process died");
351 error(SYSTEM, "error reading from server process");
352 }
353
354
355 serv_request(type, nbytes, p) /* send a request to the server process */
356 int type, nbytes;
357 char *p;
358 {
359 MSGHEAD msg;
360 int m;
361 /* get server's attention for big request */
362 if (nbytes >= BIGREQSIZ-sizeof(MSGHEAD)) {
363 serv_request(DR_ATTEN, 0, NULL);
364 while ((m = serv_result()) != DS_ACKNOW)
365 if (m == DS_SHUTDOWN) /* the bugger quit on us */
366 quit(0);
367 }
368 msg.type = type; /* write and flush the message */
369 msg.nbytes = nbytes;
370 fwrite((char *)&msg, sizeof(MSGHEAD), 1, stdout);
371 if (nbytes > 0)
372 fwrite(p, 1, nbytes, stdout);
373 if (fflush(stdout) < 0)
374 error(SYSTEM, "write error in serv_request");
375 }
376
377
378 eputs(s) /* put error message to stderr */
379 register char *s;
380 {
381 static int midline = 0;
382
383 if (!*s)
384 return;
385 if (!midline++) { /* prepend line with program name */
386 fputs(progname, stderr);
387 fputs(": ", stderr);
388 }
389 fputs(s, stderr);
390 if (s[strlen(s)-1] == '\n') {
391 fflush(stderr);
392 midline = 0;
393 }
394 }
395
396
397 quit(code) /* clean up and exit */
398 int code;
399 {
400 if (odev.v.type)
401 dev_close();
402 exit(code);
403 }