BRL-CAD
dm-rtgl.c
Go to the documentation of this file.
1 /* D M - R T G L . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1988-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file libdm/dm-rtgl.c
21  *
22  * A Ray Tracing X11 OpenGL Display Manager.
23  *
24  */
25 
26 #include "common.h"
27 
28 #ifdef DM_RTGL
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <math.h>
33 #include <string.h>
34 #include <time.h>
35 
36 #ifdef HAVE_X11_XOSDEFS_H
37 # include <X11/Xfuncproto.h>
38 # include <X11/Xosdefs.h>
39 #endif
40 #ifdef linux
41 # undef X_NOT_STDC_ENV
42 # undef X_NOT_POSIX
43 #endif
44 
45 #include <X11/extensions/XInput.h>
46 #include <GL/glx.h>
47 #include <GL/gl.h>
48 
49 #include "tk.h"
50 
51 #undef VMIN /* is used in vmath.h, too */
52 
53 #include "vmath.h"
54 #include "bn.h"
55 #include "raytrace.h"
56 #include "dm.h"
57 #include "dm-rtgl.h"
58 #include "dm/dm_xvars.h"
59 #include "fb.h"
60 #include "fb/fb_ogl.h"
61 #include "solid.h"
62 
63 #include "./dm_private.h"
64 
65 #define VIEWFACTOR (1.0/(*dmp->dm_vp))
66 #define VIEWSIZE (2.0*(*dmp->dm_vp))
67 
68 /* these are from /usr/include/gl.h could be device dependent */
69 #define XMAXSCREEN 1279
70 #define YMAXSCREEN 1023
71 #define YSTEREO 491 /* subfield height, in scanlines */
72 #define YOFFSET_LEFT 532 /* YSTEREO + YBLANK ? */
73 
74 #define USE_VECTOR_THRESHOLD 0
75 #if USE_VECTOR_THRESHOLD
76 extern int vectorThreshold; /* defined in libdm/tcl.c */
77 #endif
78 
79 static int rtgl_actively_drawing;
80 HIDDEN XVisualInfo *rtgl_choose_visual(dm *dmp, Tk_Window tkwin);
81 
82 /* Display Manager package interface */
83 #define IRBOUND 4095.9 /* Max magnification in Rot matrix */
84 #define PLOTBOUND 1000.0 /* Max magnification in Rot matrix */
85 
86 
87 dm *rtgl_open(Tcl_Interp *interp, int argc, char **argv);
88 
90 
91 
92 
93 static fastf_t default_viewscale = 1000.0;
94 static double xlim_view = 1.0; /* args for glOrtho*/
95 static double ylim_view = 1.0;
96 
97 /* lighting parameters */
98 static float amb_three[] = {0.3, 0.3, 0.3, 1.0};
99 static float light0_position[] = {0.0, 0.0, 1.0, 0.0};
100 static float light0_diffuse[] = {1.0, 1.0, 1.0, 1.0};
101 static float wireColor[4];
102 static float ambientColor[4];
103 static float specularColor[4];
104 static float diffuseColor[4];
105 
106 struct rtglJobs rtgljob = {
107  1,
108  0,
109  0,
110  NULL,
111  0,
112  0,
113  NULL,
114  NULL,
115  NULL,
116  0,
117  0
118 };
119 
120 
121 /* ray trace vars */
122 struct application app;
123 struct rt_i *rtip;
124 
125 /* free all jobs from job list */
126 void
127 freeJobList(struct jobList *jobs)
128 {
129 
130  /* list cannot be empty */
131  if (jobs->l.forw != NULL && (struct jobList *)jobs->l.forw != &(*jobs)) {
132 
133  while (BU_LIST_WHILE (rtgljob.currJob, jobList, &(jobs->l))) {
134 
135  BU_LIST_DEQUEUE(&(rtgljob.currJob->l));
136  bu_free(rtgljob.currJob, "free jobs rtgljob.currJob");
137  }
138 
139  jobs->l.forw = BU_LIST_NULL;
140  }
141 }
142 
143 
144 void
145 rtgl_fogHint(dm *dmp, int fastfog)
146 {
147  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.fastfog = fastfog;
148  glHint(GL_FOG_HINT, fastfog ? GL_FASTEST : GL_NICEST);
149 }
150 
151 
152 /*
153  * Fire up the display manager, and the display processor.
154  *
155  */
156 dm *
157 rtgl_open(Tcl_Interp *interp, int argc, char **argv)
158 {
159  static int count = 0;
160  GLfloat backgnd[4];
161  int j, k;
162  int make_square = -1;
163  int ndevices;
164  int nclass = 0;
165  int unused;
166  XDeviceInfoPtr olist = NULL, list = NULL;
167  XDevice *dev = NULL;
168  XEventClass e_class[15];
169  XInputClassInfo *cip;
170  struct bu_vls str = BU_VLS_INIT_ZERO;
171  struct bu_vls init_proc_vls = BU_VLS_INIT_ZERO;
172  Display *tmp_dpy = (Display *)NULL;
173  dm *dmp = (dm *)NULL;
174  Tk_Window tkwin = (Tk_Window)NULL;
175  int screen_number = -1;
176 
177  if ((tkwin = Tk_MainWindow(interp)) == NULL) {
178  return DM_NULL;
179  }
180 
181  BU_ALLOC(dmp, struct dm_internal);
182 
183  *dmp = dm_rtgl; /* struct copy */
184  dmp->dm_interp = interp;
185  dmp->dm_lineWidth = 1;
186 
187  BU_ALLOC(dmp->dm_vars.pub_vars, struct dm_xvars);
188  BU_ALLOC(dmp->dm_vars.priv_vars, struct rtgl_vars);
189 
190  dmp->dm_vp = &default_viewscale;
191 
192  bu_vls_init(&dmp->dm_pathName);
193  bu_vls_init(&dmp->dm_tkName);
194  bu_vls_init(&dmp->dm_dName);
195 
196  dm_processOptions(dmp, &init_proc_vls, --argc, ++argv);
197 
198  if (bu_vls_strlen(&dmp->dm_pathName) == 0)
199  bu_vls_printf(&dmp->dm_pathName, ".dm_rtgl%d", count);
200  ++count;
201  if (bu_vls_strlen(&dmp->dm_dName) == 0) {
202  char *dp;
203 
204  dp = getenv("DISPLAY");
205  if (dp)
206  bu_vls_strcpy(&dmp->dm_dName, dp);
207  else
208  bu_vls_strcpy(&dmp->dm_dName, ":0.0");
209  }
210  if (bu_vls_strlen(&init_proc_vls) == 0)
211  bu_vls_strcpy(&init_proc_vls, "bind_dm");
212 
213  rtgljob.calls = 1;
214  rtgljob.jobsDone = 1;
215 
216  /* initialize dm specific variables */
217  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->devmotionnotify = LASTEvent;
218  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->devbuttonpress = LASTEvent;
219  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->devbuttonrelease = LASTEvent;
220  dmp->dm_aspect = 1.0;
221 
222  /* initialize modifiable variables */
223  RTGL_MVARS.gedp = GED_NULL;
224  RTGL_MVARS.needRefresh = 0;
225  RTGL_MVARS.rgb = 1;
226  RTGL_MVARS.doublebuffer = 1;
227  RTGL_MVARS.fastfog = 1;
228  RTGL_MVARS.fogdensity = 1.0;
229  RTGL_MVARS.lighting_on = dmp->dm_light;
230  RTGL_MVARS.zbuffer_on = dmp->dm_zbuffer;
231  RTGL_MVARS.debug = dmp->dm_debugLevel;
232  RTGL_MVARS.bound = dmp->dm_bound;
233  RTGL_MVARS.boundFlag = dmp->dm_boundFlag;
234  RTGL_MVARS.zclipping_on = dmp->dm_zclip;
235 
236  /* this is important so that rtgl_configureWin knows to set the font */
237  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct = NULL;
238 
239  if ((tmp_dpy = XOpenDisplay(bu_vls_addr(&dmp->dm_dName))) == NULL) {
240  bu_vls_free(&init_proc_vls);
241  (void)rtgl_close(dmp);
242  return DM_NULL;
243  }
244 
245 #ifdef HAVE_XQUERYEXTENSION
246  {
247  int return_val;
248 
249  if (!XQueryExtension(tmp_dpy, "GLX", &return_val, &return_val, &return_val)) {
250  bu_vls_free(&init_proc_vls);
251  (void)rtgl_close(dmp);
252  return DM_NULL;
253  }
254  }
255 #endif
256 
257  screen_number = XDefaultScreen(tmp_dpy);
258  if (screen_number < 0)
259  bu_log("WARNING: screen number is [%d]\n", screen_number);
260 
261 
262  if (dmp->dm_width == 0) {
263  dmp->dm_width = XDisplayWidth(tmp_dpy, screen_number) - 30;
264  ++make_square;
265  }
266  if (dmp->dm_height == 0) {
267  dmp->dm_height = XDisplayHeight(tmp_dpy, screen_number) - 30;
268  ++make_square;
269  }
270 
271  if (make_square > 0) {
272  /* Make window square */
273  if (dmp->dm_height <
274  dmp->dm_width)
275  dmp->dm_width =
276  dmp->dm_height;
277  else
278  dmp->dm_height =
279  dmp->dm_width;
280  }
281 
282  XCloseDisplay(tmp_dpy);
283 
284  if (dmp->dm_top) {
285  /* Make xtkwin a toplevel window */
286  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin =
287  Tk_CreateWindowFromPath(interp,
288  tkwin,
289  bu_vls_addr(&dmp->dm_pathName),
290  bu_vls_addr(&dmp->dm_dName));
291  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->top = ((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin;
292  } else {
293  char *cp;
294 
295  cp = strrchr(bu_vls_addr(&dmp->dm_pathName), (int)'.');
296  if (cp == bu_vls_addr(&dmp->dm_pathName)) {
297  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->top = tkwin;
298  } else {
299  struct bu_vls top_vls = BU_VLS_INIT_ZERO;
300 
301  bu_vls_strncpy(&top_vls, (const char *)bu_vls_addr(&dmp->dm_pathName), cp - bu_vls_addr(&dmp->dm_pathName));
302 
303  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->top =
304  Tk_NameToWindow(interp, bu_vls_addr(&top_vls), tkwin);
305  bu_vls_free(&top_vls);
306  }
307 
308  /* Make xtkwin an embedded window */
309  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin =
310  Tk_CreateWindow(interp, ((struct dm_xvars *)dmp->dm_vars.pub_vars)->top,
311  cp + 1, (char *)NULL);
312  }
313 
314  if (((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin == NULL) {
315  bu_log("dm-Rtgl: Failed to open %s\n", bu_vls_addr(&dmp->dm_pathName));
316  bu_vls_free(&init_proc_vls);
317  (void)rtgl_close(dmp);
318  return DM_NULL;
319  }
320 
321  bu_vls_printf(&dmp->dm_tkName, "%s",
322  (char *)Tk_Name(((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin));
323 
324  bu_vls_printf(&str, "_init_dm %s %s\n",
325  bu_vls_addr(&init_proc_vls),
326  bu_vls_addr(&dmp->dm_pathName));
327 
328  if (Tcl_Eval(interp, bu_vls_addr(&str)) == TCL_ERROR) {
329  bu_vls_free(&init_proc_vls);
330  bu_vls_free(&str);
331  (void)rtgl_close(dmp);
332  return DM_NULL;
333  }
334 
335  bu_vls_free(&init_proc_vls);
336  bu_vls_free(&str);
337 
338  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy =
339  Tk_Display(((struct dm_xvars *)dmp->dm_vars.pub_vars)->top);
340 
341  /* make sure there really is a display before proceeding. */
342  if (!((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy) {
343  bu_vls_free(&init_proc_vls);
344  bu_vls_free(&str);
345  (void)rtgl_close(dmp);
346  return DM_NULL;
347  }
348 
349  Tk_GeometryRequest(((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin,
350  dmp->dm_width,
351  dmp->dm_height);
352 
353  /* must do this before MakeExist */
354  if ((((struct dm_xvars *)dmp->dm_vars.pub_vars)->vip=rtgl_choose_visual(dmp,
355  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin)) == NULL) {
356  bu_log("rtgl_open: Can't get an appropriate visual.\n");
357  (void)rtgl_close(dmp);
358  return DM_NULL;
359  }
360 
361  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->depth = ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.depth;
362 
363  Tk_MakeWindowExist(((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin);
364 
365  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win =
366  Tk_WindowId(((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin);
367  dmp->dm_id = ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win;
368 
369  /* open GLX context */
370  if ((((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc =
371  glXCreateContext(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
372  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->vip,
373  (GLXContext)NULL, GL_TRUE))==NULL) {
374  bu_log("rtgl_open: couldn't create glXContext.\n");
375  (void)rtgl_close(dmp);
376  return DM_NULL;
377  }
378 
379  /* If we used an indirect context, then as far as sgi is concerned,
380  * gl hasn't been used.
381  */
382  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->is_direct =
383  (char) glXIsDirect(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
384  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc);
385 
386  /*
387  * Take a look at the available input devices. We're looking
388  * for "dial+buttons".
389  */
390  if (XQueryExtension(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy, "XInputExtension", &unused, &unused, &unused)) {
391  olist = list = (XDeviceInfoPtr)XListInputDevices(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy, &ndevices);
392  }
393 
394  if (list == (XDeviceInfoPtr)NULL ||
395  list == (XDeviceInfoPtr)1) goto Done;
396 
397  for (j = 0; j < ndevices; ++j, list++) {
398  if (list->use == IsXExtensionDevice) {
399  if (BU_STR_EQUAL(list->name, "dial+buttons")) {
400  if ((dev = XOpenDevice(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
401  list->id)) == (XDevice *)NULL) {
402  bu_log("rtgl_open: Couldn't open the dials+buttons\n");
403  goto Done;
404  }
405 
406  for (cip = dev->classes, k = 0; k < dev->num_classes;
407  ++k, ++cip) {
408  switch (cip->input_class) {
409 #ifdef IR_BUTTONS
410  case ButtonClass:
411  DeviceButtonPress(dev, ((struct dm_xvars *)dmp->dm_vars.pub_vars)->devbuttonpress,
412  e_class[nclass]);
413  ++nclass;
414  DeviceButtonRelease(dev, ((struct dm_xvars *)dmp->dm_vars.pub_vars)->devbuttonrelease,
415  e_class[nclass]);
416  ++nclass;
417  break;
418 #endif
419 #ifdef IR_KNOBS
420  case ValuatorClass:
421  DeviceMotionNotify(dev, ((struct dm_xvars *)dmp->dm_vars.pub_vars)->devmotionnotify,
422  e_class[nclass]);
423  ++nclass;
424  break;
425 #endif
426  default:
427  break;
428  }
429  }
430 
431  XSelectExtensionEvent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
432  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win, e_class, nclass);
433  goto Done;
434  }
435  }
436  }
437 Done:
438  XFreeDeviceList(olist);
439 
440  Tk_MapWindow(((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin);
441 
442  if (!glXMakeCurrent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
443  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win,
444  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc)) {
445  bu_log("rtgl_open: Couldn't make context current\n");
446  (void)rtgl_close(dmp);
447  return DM_NULL;
448  }
449 
450  /* display list (fontOffset + char) will display a given ASCII char */
451  if ((((struct rtgl_vars *)dmp->dm_vars.priv_vars)->fontOffset = glGenLists(128))==0) {
452  bu_log("dm-rtgl: Can't make display lists for font.\n");
453  (void)rtgl_close(dmp);
454  return DM_NULL;
455  }
456 
457  /* This is the applications display list offset */
458  dmp->dm_displaylist = ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->fontOffset + 128;
459 
460  rtgl_setBGColor(dmp, 0, 0, 0);
461  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
462 
463  if (((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.doublebuffer)
464  glDrawBuffer(GL_BACK);
465  else
466  glDrawBuffer(GL_FRONT);
467 
468  /* do viewport, ortho commands and initialize font */
469  (void)rtgl_configureWin_guts(dmp, 1);
470 
471  /* Lines will be solid when stippling disabled, dashed when enabled*/
472  glLineStipple(1, 0xCF33);
473  glDisable(GL_LINE_STIPPLE);
474 
475  backgnd[0] = backgnd[1] = backgnd[2] = backgnd[3] = 0.0;
476  glFogi(GL_FOG_MODE, GL_LINEAR);
477  glFogf(GL_FOG_START, 0.0);
478  glFogf(GL_FOG_END, 2.0);
479  glFogfv(GL_FOG_COLOR, backgnd);
480 
481  /*XXX Need to do something about VIEWFACTOR */
482  glFogf(GL_FOG_DENSITY, VIEWFACTOR);
483 
484  /* Initialize matrices */
485  /* Leave it in model_view mode normally */
486  glMatrixMode(GL_PROJECTION);
487  glLoadIdentity();
488  glOrtho(-xlim_view, xlim_view, -ylim_view, ylim_view, 0.0, 2.0);
489  glGetDoublev(GL_PROJECTION_MATRIX, ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->faceplate_mat);
490  glPushMatrix();
491  glMatrixMode(GL_MODELVIEW);
492  glLoadIdentity();
493  glTranslatef(0.0, 0.0, -1.0);
494  glPushMatrix();
495  glLoadIdentity();
496  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->face_flag = 1; /* faceplate matrix is on top of stack */
497 
498  return dmp;
499 }
500 
501 
502 int
503 rtgl_share_dlist(dm *dmp1, dm *dmp2)
504 {
505  GLfloat backgnd[4];
506  GLfloat vf;
507  GLXContext old_glxContext;
508 
509  if (dmp1 == (dm *)NULL)
510  return TCL_ERROR;
511 
512  if (dmp2 == (dm *)NULL) {
513  /* create a new graphics context for dmp1 with private display lists */
514 
515  old_glxContext = ((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->glxc;
516 
517  if ((((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->glxc =
518  glXCreateContext(((struct dm_xvars *)dmp1->dm_vars.pub_vars)->dpy,
519  ((struct dm_xvars *)dmp1->dm_vars.pub_vars)->vip,
520  (GLXContext)NULL, GL_TRUE))==NULL) {
521  bu_log("rtgl_share_dlist: couldn't create glXContext.\nUsing old context\n.");
522  ((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->glxc = old_glxContext;
523 
524  return TCL_ERROR;
525  }
526 
527  if (!glXMakeCurrent(((struct dm_xvars *)dmp1->dm_vars.pub_vars)->dpy,
528  ((struct dm_xvars *)dmp1->dm_vars.pub_vars)->win,
529  ((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->glxc)) {
530  bu_log("rtgl_share_dlist: Couldn't make context current\nUsing old context\n.");
531  ((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->glxc = old_glxContext;
532 
533  return TCL_ERROR;
534  }
535 
536  /* display list (fontOffset + char) will display a given ASCII char */
537  if ((((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->fontOffset = glGenLists(128))==0) {
538  bu_log("dm-rtgl: Can't make display lists for font.\nUsing old context\n.");
539  ((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->glxc = old_glxContext;
540 
541  return TCL_ERROR;
542  }
543 
544  /* This is the applications display list offset */
545  dmp1->dm_displaylist = ((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->fontOffset + 128;
546 
547  rtgl_setBGColor(dmp1, 0, 0, 0);
548  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
549 
550  if (((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->mvars.doublebuffer)
551  glDrawBuffer(GL_BACK);
552  else
553  glDrawBuffer(GL_FRONT);
554 
555  /* this is important so that rtgl_configureWin knows to set the font */
556  ((struct dm_xvars *)dmp1->dm_vars.pub_vars)->fontstruct = NULL;
557 
558  /* do viewport, ortho commands and initialize font */
559  (void)rtgl_configureWin_guts(dmp1, 1);
560 
561  /* Lines will be solid when stippling disabled, dashed when enabled*/
562  glLineStipple(1, 0xCF33);
563  glDisable(GL_LINE_STIPPLE);
564 
565  backgnd[0] = backgnd[1] = backgnd[2] = backgnd[3] = 0.0;
566  glFogi(GL_FOG_MODE, GL_LINEAR);
567  glFogf(GL_FOG_START, 0.0);
568  glFogf(GL_FOG_END, 2.0);
569  glFogfv(GL_FOG_COLOR, backgnd);
570 
571  /*XXX Need to do something about VIEWFACTOR */
572  vf = 1.0/(*dmp1->dm_vp);
573  glFogf(GL_FOG_DENSITY, vf);
574 
575  /* Initialize matrices */
576  /* Leave it in model_view mode normally */
577  glMatrixMode(GL_PROJECTION);
578  glLoadIdentity();
579  glOrtho(-xlim_view, xlim_view, -ylim_view, ylim_view, 0.0, 2.0);
580  glGetDoublev(GL_PROJECTION_MATRIX, ((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->faceplate_mat);
581  glPushMatrix();
582  glMatrixMode(GL_MODELVIEW);
583  glLoadIdentity();
584  glTranslatef(0.0, 0.0, -1.0);
585  glPushMatrix();
586  glLoadIdentity();
587  ((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->face_flag = 1; /* faceplate matrix is on top of stack */
588 
589  /* destroy old context */
590  glXMakeCurrent(((struct dm_xvars *)dmp1->dm_vars.pub_vars)->dpy, None, NULL);
591  glXDestroyContext(((struct dm_xvars *)dmp1->dm_vars.pub_vars)->dpy, old_glxContext);
592  } else {
593  /* dmp1 will share its display lists with dmp2 */
594 
595  old_glxContext = ((struct rtgl_vars *)dmp2->dm_vars.priv_vars)->glxc;
596 
597  if ((((struct rtgl_vars *)dmp2->dm_vars.priv_vars)->glxc =
598  glXCreateContext(((struct dm_xvars *)dmp2->dm_vars.pub_vars)->dpy,
599  ((struct dm_xvars *)dmp2->dm_vars.pub_vars)->vip,
600  ((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->glxc,
601  GL_TRUE))==NULL) {
602  bu_log("rtgl_share_dlist: couldn't create glXContext.\nUsing old context\n.");
603  ((struct rtgl_vars *)dmp2->dm_vars.priv_vars)->glxc = old_glxContext;
604 
605  return TCL_ERROR;
606  }
607 
608  if (!glXMakeCurrent(((struct dm_xvars *)dmp2->dm_vars.pub_vars)->dpy,
609  ((struct dm_xvars *)dmp2->dm_vars.pub_vars)->win,
610  ((struct rtgl_vars *)dmp2->dm_vars.priv_vars)->glxc)) {
611  bu_log("rtgl_share_dlist: Couldn't make context current\nUsing old context\n.");
612  ((struct rtgl_vars *)dmp2->dm_vars.priv_vars)->glxc = old_glxContext;
613 
614  return TCL_ERROR;
615  }
616 
617  ((struct rtgl_vars *)dmp2->dm_vars.priv_vars)->fontOffset = ((struct rtgl_vars *)dmp1->dm_vars.priv_vars)->fontOffset;
618  dmp2->dm_displaylist = dmp1->dm_displaylist;
619 
620  rtgl_setBGColor(dmp2, 0, 0, 0);
621  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
622 
623  if (((struct rtgl_vars *)dmp2->dm_vars.priv_vars)->mvars.doublebuffer)
624  glDrawBuffer(GL_BACK);
625  else
626  glDrawBuffer(GL_FRONT);
627 
628  /* do viewport, ortho commands and initialize font */
629  (void)rtgl_configureWin_guts(dmp2, 1);
630 
631  /* Lines will be solid when stippling disabled, dashed when enabled*/
632  glLineStipple(1, 0xCF33);
633  glDisable(GL_LINE_STIPPLE);
634 
635  backgnd[0] = backgnd[1] = backgnd[2] = backgnd[3] = 0.0;
636  glFogi(GL_FOG_MODE, GL_LINEAR);
637  glFogf(GL_FOG_START, 0.0);
638  glFogf(GL_FOG_END, 2.0);
639  glFogfv(GL_FOG_COLOR, backgnd);
640 
641  /*XXX Need to do something about VIEWFACTOR */
642  vf = 1.0/(*dmp2->dm_vp);
643  glFogf(GL_FOG_DENSITY, vf);
644 
645  /* Initialize matrices */
646  /* Leave it in model_view mode normally */
647  glMatrixMode(GL_PROJECTION);
648  glLoadIdentity();
649  glOrtho(-xlim_view, xlim_view, -ylim_view, ylim_view, 0.0, 2.0);
650  glGetDoublev(GL_PROJECTION_MATRIX, ((struct rtgl_vars *)dmp2->dm_vars.priv_vars)->faceplate_mat);
651  glPushMatrix();
652  glMatrixMode(GL_MODELVIEW);
653  glLoadIdentity();
654  glTranslatef(0.0, 0.0, -1.0);
655  glPushMatrix();
656  glLoadIdentity();
657  ((struct rtgl_vars *)dmp2->dm_vars.priv_vars)->face_flag = 1; /* faceplate matrix is on top of stack */
658 
659  /* destroy old context */
660  glXMakeCurrent(((struct dm_xvars *)dmp2->dm_vars.pub_vars)->dpy, None, NULL);
661  glXDestroyContext(((struct dm_xvars *)dmp2->dm_vars.pub_vars)->dpy, old_glxContext);
662  }
663 
664  return TCL_OK;
665 }
666 
667 
668 /*
669  * Gracefully release the display.
670  */
671 HIDDEN int
672 rtgl_close(dm *dmp)
673 {
674  if (((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy) {
675  if (((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc) {
676  glXMakeCurrent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy, None, NULL);
677  glXDestroyContext(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
678  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc);
679  }
680 
681  if (((struct dm_xvars *)dmp->dm_vars.pub_vars)->cmap)
682  XFreeColormap(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
683  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->cmap);
684 
685  if (((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin)
686  Tk_DestroyWindow(((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin);
687  }
688 
689  bu_vls_free(&dmp->dm_pathName);
690  bu_vls_free(&dmp->dm_tkName);
691  bu_vls_free(&dmp->dm_dName);
692  bu_free(dmp->dm_vars.priv_vars, "rtgl_close: rtgl_vars");
693  bu_free(dmp->dm_vars.pub_vars, "rtgl_close: dm_xvars");
694  bu_free(dmp, "rtgl_close: dmp");
695 
696  /* reset job count */
697  rtgljob.controlClip = 1;
698  rtgljob.calls = 0;
699  rtgljob.jobsDone = 0;
700  rtgljob.numTrees = 0;
701  rtgljob.numJobs = 0;
702  rtgljob.rtglWasClosed = 1;
703 
704  /* release trees */
705  if (rtgljob.oldTrees != NULL)
706  bu_free(rtgljob.oldTrees, "free oldTrees");
707  rtgljob.oldTrees = (char **)NULL;
708  rtgljob.treeCapacity = 0;
709 
710  /* free draw list */
711  if (rtgljob.colorTable != NULL) {
712  bu_hash_tbl_free(rtgljob.colorTable);
713  rtgljob.colorTable = NULL;
714  }
715 
716  rtgljob.currItem = NULL;
717  rtgljob.currJob = NULL;
718 
719  return TCL_OK;
720 }
721 
722 
723 /* stash a new job into a dynamically allocated container */
724 HIDDEN void
725 rtgl_stashTree(struct rtglJobs *job, char *tree)
726 {
727  static const size_t STEP = 1024;
728 
729  /* make sure there is enough room */
730  if (job->treeCapacity == 0) {
731  job->oldTrees = (char **)bu_calloc(STEP, sizeof(char *), "called oldTrees");
732  job->treeCapacity = STEP;
733  } else if (job->numTrees + 1 >= job->treeCapacity) {
734  job->oldTrees = (char **)bu_realloc(job->oldTrees, (sizeof(char *) * job->treeCapacity) + STEP, "realloc oldTrees");
735  job->treeCapacity += STEP;
736  }
737 
738  /* add it */
739  job->oldTrees[job->numTrees] = tree;
740  job->numTrees++;
741 }
742 
743 
744 /*
745  * There are global variables which are parameters to this routine.
746  */
747 HIDDEN int
748 rtgl_drawBegin(dm *dmp)
749 {
750  GLfloat fogdepth;
751 
752  if (dmp->dm_debugLevel) {
753  bu_log("rtgl_drawBegin\n");
754 
755  if (rtgl_actively_drawing)
756  bu_log("rtgl_drawBegin: already actively drawing\n");
757  }
758 
759  rtgl_actively_drawing = 1;
760 
761  if (!glXMakeCurrent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
762  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win,
763  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc)) {
764  bu_log("rtgl_drawBegin: Couldn't make context current\n");
765  return TCL_ERROR;
766  }
767 
768  /* clear back buffer */
769  if (!dmp->dm_clearBufferAfter &&
770  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.doublebuffer) {
771  glClearColor(((struct rtgl_vars *)dmp->dm_vars.priv_vars)->r,
772  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->g,
773  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->b,
774  0.0);
775  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
776  }
777 
778  if (((struct rtgl_vars *)dmp->dm_vars.priv_vars)->face_flag) {
779  glMatrixMode(GL_PROJECTION);
780  glPopMatrix();
781  glMatrixMode(GL_MODELVIEW);
782  glPopMatrix();
783  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->face_flag = 0;
784  if (((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.cueing_on) {
785  glEnable(GL_FOG);
786  /*XXX Need to do something with Viewscale */
787  fogdepth = 2.2 * (*dmp->dm_vp); /* 2.2 is heuristic */
788  glFogf(GL_FOG_END, fogdepth);
789  fogdepth = (GLfloat) (0.5*((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.fogdensity/
790  (*dmp->dm_vp));
791  glFogf(GL_FOG_DENSITY, fogdepth);
792  glFogi(GL_FOG_MODE, dmp->dm_perspective ? GL_EXP : GL_LINEAR);
793  }
794  if (dmp->dm_light) {
795  glEnable(GL_LIGHTING);
796  }
797  }
798 
799  return TCL_OK;
800 }
801 
802 
803 HIDDEN int
804 rtgl_drawEnd(dm *dmp)
805 {
806  if (dmp->dm_debugLevel)
807  bu_log("rtgl_drawEnd\n");
808 
809 
810  if (dmp->dm_light) {
811  glMatrixMode(GL_MODELVIEW);
812  glLoadIdentity();
813  glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
814  }
815 
816  if (((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.doublebuffer) {
817  glXSwapBuffers(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
818  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win);
819 
820  if (dmp->dm_clearBufferAfter) {
821  /* give Graphics pipe time to work */
822  glClearColor(((struct rtgl_vars *)dmp->dm_vars.priv_vars)->r,
823  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->g,
824  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->b,
825  0.0);
826  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
827  }
828  }
829 
830  if (dmp->dm_debugLevel) {
831  int error;
832  struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
833 
834  bu_vls_printf(&tmp_vls, "ANY ERRORS?\n");
835 
836  while ((error = glGetError())!=0) {
837  bu_vls_printf(&tmp_vls, "Error: %x\n", error);
838  }
839 
840  bu_log("%s", bu_vls_addr(&tmp_vls));
841  bu_vls_free(&tmp_vls);
842  }
843 
844  rtgl_actively_drawing = 0;
845  return TCL_OK;
846 }
847 
848 
849 double startScale = 1;
850 
851 /*
852  * Load a new transformation matrix. This will be followed by
853  * many calls to rtgl_draw().
854  */
855 HIDDEN int
856 rtgl_loadMatrix(dm *dmp, fastf_t *mat, int which_eye)
857 {
858  mat_t newm;
859 
860  fastf_t clip, scale = 1;
861 
862  mat_t zclip;
863 
864  /* get ged struct */
865  struct ged *gedp = RTGL_GEDP;
866 
867  if (gedp != GED_NULL) {
868 
869  /* calculate scale factor for clipping */
870  scale = 1 / gedp->ged_gvp->gv_isize;
871 
872  if (startScale == 1) {
873  startScale = scale;
874  }
875  }
876 
877  if (dmp->dm_debugLevel) {
878  struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
879 
880  bu_log("rtgl_loadMatrix()\n");
881 
882  bu_vls_printf(&tmp_vls, "which eye = %d\t", which_eye);
883  bu_vls_printf(&tmp_vls, "transformation matrix = \n");
884  bu_vls_printf(&tmp_vls, "%g %g %g %g\n", mat[0], mat[4], mat[8], mat[12]);
885  bu_vls_printf(&tmp_vls, "%g %g %g %g\n", mat[1], mat[5], mat[9], mat[13]);
886  bu_vls_printf(&tmp_vls, "%g %g %g %g\n", mat[2], mat[6], mat[10], mat[14]);
887  bu_vls_printf(&tmp_vls, "%g %g %g %g\n", mat[3], mat[7], mat[11], mat[15]);
888 
889  bu_log("%s", bu_vls_addr(&tmp_vls));
890  bu_vls_free(&tmp_vls);
891  }
892 
893  switch (which_eye) {
894  case 0:
895  /* Non-stereo */
896  break;
897  case 1:
898  /* R eye */
899  glViewport(0, 0, (XMAXSCREEN)+1, (YSTEREO)+1);
900  glScissor(0, 0, (XMAXSCREEN)+1, (YSTEREO)+1);
901  rtgl_drawString2D(dmp, "R", 0.986, 0.0, 0, 1);
902  break;
903  case 2:
904  /* L eye */
905  glViewport(0, 0+YOFFSET_LEFT, (XMAXSCREEN)+1,
906  (YSTEREO+YOFFSET_LEFT)-(YOFFSET_LEFT)+1);
907  glScissor(0, 0+YOFFSET_LEFT, (XMAXSCREEN)+1,
908  (YSTEREO+YOFFSET_LEFT)-(YOFFSET_LEFT)+1);
909  break;
910  }
911 
912  MAT_IDN(zclip);
913 
914  /* use z-clipping */
915  if (dmp->dm_zclip) {
916 
917  /* use custom clipping to control zbuffer precision */
918  if (rtgljob.controlClip) {
919  clip = scale / startScale - .75;
920 
921  if (clip > 1)
922  clip = 1;
923  if (clip < .001)
924  clip = .001;
925 
926  /* [0, 1], smaller value implies larger volume (less
927  * clipping) in z direction, but less precision
928  */
929  zclip[10] = clip;
930  } else {
931  /* use default z clipping */
932  zclip[10] = dmp->dm_bound;
933  }
934  } else {
935  /* prevent z-clipping */
936  zclip[10] = 1e-20;
937  }
938 
939  /* apply clip to view matrix */
940  bn_mat_mul(newm, zclip, mat);
941 
942  glMatrixMode(GL_MODELVIEW);
943  glLoadIdentity();
944 
945  /* set light position now, so that it moves with the view */
946  {
947  GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
948  GLfloat white_light[] = { .5, .5, .5, 1.0 };
949  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
950  glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
951  glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);
952  }
953 
954  {
955  GLfloat lmodel_ambient[] = { 0.1, 0.1, 0.1, 1.0 };
956  glShadeModel(GL_FLAT);
957  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
958  glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
959  glLightModelf(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
960  }
961 
962  glEnable(GL_LIGHTING);
963  glEnable(GL_LIGHT0);
964  glEnable(GL_RESCALE_NORMAL);
965 
966  /* apply view */
967  if (rtgljob.controlClip) {
968  /* move clipping volume when zooming-in
969  * to prevent clipping front surfaces
970  */
971  glTranslatef(0.0, 0.0, clip - 1.75);
972  } else {
973  glTranslatef(0.0, 0.0, -1.0);
974  }
975 
976  /* transpose to OpenGL format before applying view */
977  glMultTransposeMatrixd(newm);
978 
979  return TCL_OK;
980 }
981 
982 
983 /* convert color vector to unsigned char array */
984 HIDDEN unsigned char *
985 getColorKey(float *color)
986 {
987  int i, value;
988  unsigned char* key = bu_malloc(sizeof(char) * KEY_LENGTH, "dm-rtgl.c: getColorKey");
989 
990  for (i = 0; i < KEY_LENGTH; i++) {
991  value = color[i] * 255;
992  key[i] = value;
993  }
994 
995  return key;
996 }
997 
998 
999 /* calculate and add hit-point info to info list */
1000 HIDDEN void
1001 addInfo(struct application *app, struct hit *hit, struct soltab *soltab, char flip, float *partColor)
1002 {
1003  point_t point;
1004  vect_t normal;
1005  int newColor;
1006  unsigned long index;
1007  unsigned char *colorKey;
1008  struct bu_hash_entry *prev, *entry;
1009  struct colorBin *bin;
1010  struct bu_list *head;
1011 
1012  /* calculate intersection point */
1013  VJOIN1(point, app->a_ray.r_pt, hit->hit_dist, app->a_ray.r_dir);
1014 
1015  /* hack fix for bad tgc surfaces */
1016  if (bu_strncmp("rec", soltab->st_meth->ft_label, 3) == 0 || bu_strncmp("tgc", soltab->st_meth->ft_label, 3) == 0) {
1017 
1018  /* correct invalid surface number */
1019  if (hit->hit_surfno < 1 || hit->hit_surfno > 3) {
1020  hit->hit_surfno = 2;
1021  }
1022  }
1023 
1024  /* calculate normal vector */
1025  RT_HIT_NORMAL(normal, hit, soltab, &(app->a_ray), flip);
1026 
1027  /* find the table bin for this color */
1028  colorKey = getColorKey(partColor);
1029  entry = bu_hash_tbl_find(rtgljob.colorTable, colorKey, KEY_LENGTH, &prev, &index);
1030 
1031  /* look for the correct color bin in the found entries */
1032  newColor = 1;
1033 
1034  while (entry != NULL) {
1035  bin = (struct colorBin *)bu_get_hash_value(entry);
1036 
1037  if (VEQUAL(bin->color, partColor)) {
1038  newColor = 0;
1039  break;
1040  }
1041 
1042  entry = entry->next;
1043  }
1044 
1045  /* have to make color bin for new color*/
1046  if (newColor) {
1047 
1048  /* create new color bin */
1049  BU_ALLOC(bin, struct colorBin);
1050  VMOVE(bin->color, partColor);
1051 
1052  /* create bin list head */
1053  BU_ALLOC(bin->list, struct ptInfoList);
1054  head = &(bin->list->l);
1055  BU_LIST_INIT(head);
1056 
1057  /* add first list item */
1058  BU_ALLOC(rtgljob.currItem, struct ptInfoList);
1059  BU_LIST_PUSH(head, rtgljob.currItem);
1060  rtgljob.currItem->used = 0;
1061 
1062  /* add the new bin to the table */
1063  entry = bu_hash_tbl_add(rtgljob.colorTable, colorKey, KEY_LENGTH, &newColor);
1064  bu_set_hash_value(entry, (unsigned char *)bin);
1065  } else {
1066  /* found existing color bin */
1067 
1068  /* get bin's current list item */
1069  head = &(bin->list->l);
1070  rtgljob.currItem = (struct ptInfoList *)head->forw;
1071 
1072  /* if list item is full, create a new item */
1073  if (rtgljob.currItem->used == PT_ARRAY_SIZE) {
1074 
1075  BU_ALLOC(rtgljob.currItem, struct ptInfoList);
1076  BU_LIST_PUSH(head, rtgljob.currItem);
1077  rtgljob.currItem->used = 0;
1078  }
1079  }
1080 
1081  /* add point and normal to bin's current list */
1082  rtgljob.currItem->points[X + rtgljob.currItem->used] = point[X];
1083  rtgljob.currItem->points[Y + rtgljob.currItem->used] = point[Y];
1084  rtgljob.currItem->points[Z + rtgljob.currItem->used] = point[Z];
1085 
1086  rtgljob.currItem->norms[X + rtgljob.currItem->used] = normal[X];
1087  rtgljob.currItem->norms[Y + rtgljob.currItem->used] = normal[Y];
1088  rtgljob.currItem->norms[Z + rtgljob.currItem->used] = normal[Z];
1089 
1090  rtgljob.currItem->used += 3;
1091 }
1092 
1093 
1094 /* add all hit point info to info list */
1095 HIDDEN int
1096 recordHit(struct application *app, struct partition *partH, struct seg *UNUSED(segs))
1097 {
1098  struct partition *part;
1099  struct soltab *soltab;
1100  float *partColor;
1101 
1102  RT_CK_APPLICATION(app);
1103 
1104  /* add all hit points */
1105  for (part = partH->pt_forw; part != partH; part = part->pt_forw) {
1106 
1107  partColor = part->pt_regionp->reg_mater.ma_color;
1108 
1109  /* add "in" hit point info */
1110  soltab = part->pt_inseg->seg_stp;
1111  addInfo(app, part->pt_inhit, soltab, part->pt_inflip, partColor);
1112 
1113  /* add "out" hit point info (unless half-space) */
1114  soltab = part->pt_inseg->seg_stp;
1115 
1116  if (bu_strncmp("half", soltab->st_meth->ft_label, 4) != 0) {
1117 
1118  addInfo(app, part->pt_outhit, soltab, part->pt_outflip, partColor);
1119  }
1120  }
1121 
1122  return 1;
1123 }
1124 
1125 
1126 /* don't care about misses */
1127 HIDDEN int
1128 ignoreMiss(struct application *app)
1129 {
1130  RT_CK_APPLICATION(app);
1131  return 0;
1132 }
1133 
1134 
1135 HIDDEN double
1136 jitter(double range)
1137 {
1138  if (rand() % 2)
1139  return fmod(rand(), range);
1140 
1141  return (-1 *(fmod(rand(), range)));
1142 }
1143 
1144 
1145 HIDDEN void
1146 randShots(fastf_t *center, fastf_t radius, int flag)
1147 {
1148  int i, j;
1149  vect_t view, dir;
1150  point_t pt;
1151  view[2] = 0;
1152 
1153  glDisable(GL_LIGHTING);
1154 
1155  for (i = 0; i < 360; i += 1) {
1156  for (j = 0; j < 90; j += 1) {
1157  view[0] = i;
1158  view[1] = j;
1159 
1160  /* use view vector for direction */
1161  bn_vec_aed(dir, view[0]*DEG2RAD, view[1]*DEG2RAD, radius);
1162  VADD2(dir, dir, center);
1163  VMOVE(app.a_ray.r_pt, dir);
1164 
1165  /* use opposite sphere point for origin */
1166  VSUB2(pt, dir, center);
1167  VREVERSE(pt, pt);
1168  VADD2(pt, pt, center);
1169 
1170  /* jitter point */
1171  VMOVE(app.a_ray.r_dir, pt);
1172 
1173  if (flag) {
1174  /* shoot ray */
1175  rt_shootray(&app);
1176  }
1177 
1178  if (!flag) {
1179  glPointSize(5);
1180  glBegin(GL_POINTS);
1181  glColor3d(0.0, 1.0, 0.0);
1182  glVertex3dv(pt);
1183  glColor3d(1.0, 0.0, 0.0);
1184  glVertex3dv(dir);
1185  glEnd();
1186 
1187  glColor4d(0.0, 0.0, 1.0, .1);
1188  glBegin(GL_LINES);
1189  glVertex3dv(pt);
1190  glVertex3dv(dir);
1191  glEnd();
1192  }
1193  }
1194  }
1195 
1196  glEnable(GL_LIGHTING);
1197 }
1198 
1199 
1200 HIDDEN void
1201 swapItems(struct bu_list *a, struct bu_list *b)
1202 {
1203  struct bu_list temp;
1204 
1205  if (a->forw == b) {
1206  /* a immediately followed by b */
1207 
1208  /* fix surrounding links */
1209  a->back->forw = b;
1210  b->forw->back = a;
1211 
1212  /* fix a and b links */
1213  a->forw = b->forw;
1214  b->back = a->back;
1215  a->back = b;
1216  b->forw = a;
1217  } else if (b->forw == a) {
1218  /* b immediately followed by a */
1219 
1220  /* fix surrounding links */
1221  b->back->forw = a;
1222  a->forw->back = b;
1223 
1224  /* fix a and b links */
1225  b->forw = a->forw;
1226  a->back = b->back;
1227  b->back = a;
1228  a->forw = b;
1229  } else {
1230  /* general case */
1231 
1232  /* fix surrounding links */
1233  a->back->forw = b;
1234  a->forw->back = b;
1235 
1236  b->back->forw = a;
1237  b->forw->back = a;
1238 
1239  /* switch a and b links */
1240  temp.forw = a->forw;
1241  temp.back = a->back;
1242 
1243  a->forw = b->forw;
1244  a->back = b->back;
1245 
1246  b->forw = temp.forw;
1247  b->back = temp.back;
1248  }
1249 }
1250 
1251 
1252 struct jobList **jobsArray = NULL;
1253 
1254 /* get nth job from job list */
1255 HIDDEN struct job*
1256 getJob(size_t n)
1257 {
1258  size_t bin, index, start;
1259 
1260  if (n > rtgljob.numJobs)
1261  return (struct job *)NULL;
1262 
1263  n--; /* meta-index of nth item */
1264 
1265  /* determine what bin holds the nth item */
1266  bin = (double) n / JOB_ARRAY_SIZE;
1267 
1268  /* meta-index of first item in bin */
1269  start = bin * JOB_ARRAY_SIZE;
1270 
1271  /* actual index of nth item in bin */
1272  index = n - start;
1273 
1274  /* get the bin link */
1275  rtgljob.currJob = jobsArray[bin];
1276 
1277  return &(rtgljob.currJob->jobs[index]);
1278 }
1279 
1280 
1281 /* Fisher-Yates shuffle */
1282 HIDDEN void
1283 shuffleJobs(void)
1284 {
1285  int i;
1286  struct job *a, *b, temp;
1287 
1288  for (i = rtgljob.numJobs; i > 0; i--) {
1289 
1290  a = getJob(i);
1291  b = getJob((rand() % i) + 1);
1292 
1293  /* swap current and rand element */
1294  COPY_JOB(temp, *a);
1295  COPY_JOB(*a, *b);
1296  COPY_JOB(*b, temp);
1297  }
1298 }
1299 
1300 
1301 /* add jobs for an even grid of parallel rays in a principle direction */
1302 HIDDEN void
1303 shootGrid(struct jobList *jobs, vect_t min, vect_t max, double maxSpan, int pixels, int uAxis, int vAxis, int iAxis)
1304 {
1305  int i, j;
1306  vect_t span;
1307  int uDivs, vDivs;
1308  fastf_t uWidth, vWidth;
1309 
1310  fastf_t uOff;
1311  fastf_t u, v;
1312 
1313  /* calculate span in each dimension */
1314  VSUB2(span, max, min);
1315 
1316  /* calculate firing intervals (trying to achieve pixel density) */
1317  uDivs = pixels * (span[uAxis] / maxSpan);
1318  vDivs = pixels * (span[vAxis] / maxSpan);
1319 
1320  /* provides an easy means to toggle quality during development */
1321 #if 0
1322  uDivs /= 2;
1323  vDivs /= 2;
1324 #endif
1325 
1326  uWidth = span[uAxis] / uDivs;
1327  vWidth = span[vAxis] / vDivs;
1328 
1329  /* calculate starting offsets */
1330  u = uOff = min[uAxis] - (uWidth / 2);
1331  v = min[vAxis] - (vWidth / 2);
1332 
1333  /* set direction */
1334  app.a_ray.r_dir[uAxis] = 0;
1335  app.a_ray.r_dir[vAxis] = 0;
1336  app.a_ray.r_dir[iAxis] = -1;
1337 
1338  app.a_ray.r_pt[iAxis] = max[iAxis] + 100;
1339 
1340  for (i = 0; i < vDivs; i++) {
1341  v += vWidth;
1342 
1343  for (j = 0; j < uDivs; j++) {
1344  u += uWidth;
1345 
1346  app.a_ray.r_pt[uAxis] = u;
1347  app.a_ray.r_pt[vAxis] = v;
1348 
1349  /* make new job if needed */
1350  if (rtgljob.currJob->used == JOB_ARRAY_SIZE) {
1351 
1352  BU_ALLOC(rtgljob.currJob, struct jobList);
1353  BU_LIST_PUSH(&(jobs->l), rtgljob.currJob);
1354  rtgljob.currJob->used = 0;
1355  }
1356 
1357  VMOVE(rtgljob.currJob->jobs[rtgljob.currJob->used].pt, app.a_ray.r_pt);
1358  VMOVE(rtgljob.currJob->jobs[rtgljob.currJob->used].dir, app.a_ray.r_dir);
1359 
1360  rtgljob.currJob->used++;
1361 
1362  rtgljob.numJobs++;
1363  }
1364 
1365  /* reset u */
1366  u = uOff;
1367  }
1368 }
1369 
1370 
1371 int numShot = 0;
1372 
1373 /* return 1 if all jobs done, 0 if not */
1374 HIDDEN int
1375 shootJobs(struct jobList *jobs)
1376 {
1377  int i, last, *used;
1378  double elapsed_time;
1379 
1380  /* list cannot be empty */
1381  if (jobsArray != NULL) {
1382 
1383  /* get last non-null item */
1384  last = rtgljob.numJobs - numShot;
1385  last /= JOB_ARRAY_SIZE;
1386  last++;
1387 
1388  while (jobsArray[last] == NULL) {
1389  last--;
1390  }
1391 
1392  /* last to first item */
1393  for (i = last; i >= 0; i--) {
1394 
1395  rtgljob.currJob = jobsArray[i];
1396  used = &(rtgljob.currJob->used);
1397 
1398  /* shoot jobs in this array */
1399  while (*used > 0) {
1400 
1401  VMOVE(app.a_ray.r_pt, rtgljob.currJob->jobs[*used].pt);
1402  VMOVE(app.a_ray.r_dir, rtgljob.currJob->jobs[*used].dir);
1403  rt_shootray(&app);
1404 
1405  numShot++;
1406  (*used)--;
1407 
1408  if (*used == 0) {
1409  BU_LIST_DEQUEUE(&(rtgljob.currJob->l));
1410  bu_free(rtgljob.currJob, "free jobs rtgljob.currJob");
1411  jobsArray[i] = NULL;
1412  break;
1413  }
1414 
1415  (void)rt_get_timer((struct bu_vls *)0, &elapsed_time);
1416  if (elapsed_time > .1) /* 100ms */
1417  return 0;
1418  }
1419  }
1420 
1421  jobs->l.forw = BU_LIST_NULL;
1422  }
1423 
1424  return 1;
1425 }
1426 
1427 
1428 HIDDEN void
1429 drawPoints(float *view, int pointSize)
1430 {
1431  int i, used;
1432  float *point, *normal, dot;
1433  struct colorBin *bin;
1434  struct bu_list *head;
1435  struct bu_hash_entry *entry;
1436  struct bu_hash_record record;
1437 
1438  /* get first table entry */
1439  if ((entry = bu_hash_tbl_first(rtgljob.colorTable, &record)) == NULL)
1440  return;
1441 
1442  /* drawing shaded points */
1443  glEnable(GL_LIGHTING);
1444  glPointSize(pointSize);
1445 
1446  /* for all table entries */
1447  do {
1448 
1449  /* get color bin from entry */
1450  bin = (struct colorBin *)bu_get_hash_value(entry);
1451 
1452  /* set color for bin */
1453  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bin->color);
1454 
1455  /* visit each item in bin's list */
1456  head = &(bin->list->l);
1457 
1458  for (BU_LIST_FOR (rtgljob.currItem, ptInfoList, head)) {
1459  used = rtgljob.currItem->used;
1460 
1461  glBegin(GL_POINTS);
1462  for (i = 0; i < used; i += 3) {
1463 
1464  point = &(rtgljob.currItem->points[i]);
1465  normal = &(rtgljob.currItem->norms[i]);
1466 
1467  /* draw if visible */
1468  dot = VDOT(view, normal);
1469 
1470  if (dot > 0) {
1471  glNormal3fv(normal); /* MUST specify normal first */
1472  glVertex3fv(point);
1473  }
1474  }
1475  glEnd();
1476  }
1477  } while ((entry = bu_hash_tbl_next(&record)) != NULL);
1478 
1479  glDisable(GL_LIGHTING);
1480  glPointSize(1);
1481 }
1482 
1483 
1484 vect_t min, max, center, view, vect;
1485 fastf_t radius;
1486 double maxSpan;
1487 time_t start = 0;
1488 
1489 HIDDEN int
1490 rtgl_drawVList(dm *dmp, struct bn_vlist *UNUSED(vp))
1491 {
1492  size_t i, j, new, numNew, maxPixels, viewSize;
1493  vect_t span;
1494  char *currTree;
1495  struct db_i *dbip;
1496  struct jobList jobs;
1497 
1498  size_t numVisible = 0;
1499  size_t visibleCount = 0;
1500  char **visibleTrees = NULL;
1501 
1502  int foundalloldtrees = 1;
1503  int foundthistree = 0;
1504 
1505  /* get ged struct */
1506  struct ged *gedp = RTGL_GEDP;
1507 
1508  if (gedp == GED_NULL)
1509  return TCL_ERROR;
1510 
1511  /* get database instance */
1512  dbip = gedp->ged_wdbp->dbip;
1513 
1514  if (dbip == DBI_NULL)
1515  return TCL_ERROR;
1516 
1517  /* get new ray trace instance */
1518  rtip = rt_new_rti(dbip);
1519 
1520  if (rtip == RTI_NULL)
1521  return TCL_ERROR;
1522 
1523  /* get view dimension information */
1524  if (dmp->dm_height > dmp->dm_width) {
1525  maxPixels = dmp->dm_height;
1526  } else {
1527  maxPixels = dmp->dm_width;
1528  }
1529 
1530  viewSize = gedp->ged_gvp->gv_size;
1531 
1532  /* initialize draw list */
1533  if (rtgljob.calls == 1 || rtgljob.colorTable == NULL) {
1534 
1535  /* create color hash table */
1537  }
1538 
1539  /* allocate our visible trees */
1540  visibleCount = ged_count_tops(gedp);
1541  if (visibleCount) {
1542  visibleTrees = (char **)bu_calloc(visibleCount, sizeof(char *), "alloc visibleTrees");
1543 
1544  /* get number and names of visible tree tops */
1545  numVisible = ged_build_tops(gedp, visibleTrees, &visibleTrees[visibleCount]);
1546 
1547  for (i = 0; i < rtgljob.numTrees; i++) {
1548  currTree = rtgljob.oldTrees[i];
1549  foundthistree = 0;
1550  for (j = 0; j < numVisible; j++) {
1551  if (BU_STR_EQUAL(currTree, visibleTrees[j]))
1552  foundthistree = 1;
1553  }
1554  if (foundthistree == 0) foundalloldtrees = 0;
1555  }
1556 
1557  /* display out of date */
1558  if (foundalloldtrees == 0) {
1559 
1560  foundalloldtrees = 1;
1561 
1562  /* drop previous work */
1563  rtgljob.numTrees = 0;
1564  freeJobList(&jobs);
1565 
1566  if (rtgljob.colorTable != NULL) {
1567  bu_hash_tbl_free(rtgljob.colorTable);
1568  rtgljob.colorTable = NULL;
1569  }
1570 
1571  if (jobsArray != NULL) {
1572  bu_free(jobsArray, "dm-rtgl.c: jobsArray");
1573  jobsArray = NULL;
1574  }
1575 
1576  RTGL_DIRTY = 1;
1577 
1578  maxSpan = 0.0;
1579  numShot = rtgljob.numJobs = 0;
1580  }
1581  } else {
1582  numVisible = 0;
1583  }
1584 
1585  /* no objects are visible */
1586  if (numVisible == 0) {
1587 
1588  /* drop previous work */
1589  rtgljob.numTrees = 0;
1590  freeJobList(&jobs);
1591 
1592  if (rtgljob.colorTable != NULL) {
1593  bu_hash_tbl_free(rtgljob.colorTable);
1594  rtgljob.colorTable = NULL;
1595  }
1596 
1597  if (jobsArray != NULL) {
1598  bu_free(jobsArray, "dm-rtgl.c: jobsArray");
1599  jobsArray = NULL;
1600  }
1601 
1602  RTGL_DIRTY = 0;
1603 
1604  /* reset for dynamic z-clipping */
1605  if (dmp->dm_zclip) {
1606  startScale = 1;
1607  }
1608 
1609  maxSpan = 0.0;
1610  numShot = rtgljob.numJobs = 0;
1611 
1612  return TCL_OK;
1613  }
1614 
1615  /* look for new trees in need of ray tracing */
1616  numNew = 0;
1617 
1618  if (rtgljob.rtglWasClosed == 1) {
1619  rtgljob.rtglWasClosed = 0;
1620  rtgljob.numTrees = 0;
1621  /* drop previous work */
1622  freeJobList(&jobs);
1623 
1624  if (rtgljob.colorTable != NULL) {
1625  bu_hash_tbl_free(rtgljob.colorTable);
1626  rtgljob.colorTable = NULL;
1627  }
1628 
1629  if (jobsArray != NULL) {
1630  bu_free(jobsArray, "dm-rtgl.c: jobsArray");
1631  jobsArray = NULL;
1632  }
1633 
1634  RTGL_DIRTY = 0;
1635 
1636  /* reset for dynamic z-clipping */
1637  if (dmp->dm_zclip) {
1638  startScale = 1;
1639  }
1640 
1641  maxSpan = 0.0;
1642  numShot = rtgljob.numJobs = 0;
1643  }
1644 
1645 
1646  for (i = 0; i < numVisible; i++) {
1647  currTree = visibleTrees[i];
1648  new = 1;
1649 
1650  /* if this tree is in the old tree list, it's not new
1651  * if it's NOT in the old list, it needs to be cleared,
1652  * but that's not set up yet without clearing everything
1653  * first and starting over.
1654  */
1655  for (j = 0; j < rtgljob.numTrees; j++) {
1656  if (BU_STR_EQUAL(currTree, rtgljob.oldTrees[j]))
1657  new = 0;
1658  }
1659 
1660  if (new) {
1661  /* will ray trace new tree*/
1662  if (rt_gettree(rtip, currTree) < 0)
1663  return TCL_ERROR;
1664 
1665  /* add new tree to list of displayed */
1666  numNew++;
1667  rtgl_stashTree(&rtgljob, currTree);
1668  }
1669  }
1670 
1671  /* get points for new trees */
1672  if (numNew > 0) {
1673  /* If we're still in progress on something,
1674  * adding another job is Bad given current
1675  * setup - for now, punt and start over.
1676  */
1677  if (rtgljob.numJobs != 0) {
1678  freeJobList(&jobs);
1679  if (rtgljob.colorTable != NULL) {
1680  bu_hash_tbl_free(rtgljob.colorTable);
1681  rtgljob.colorTable = NULL;
1682  }
1683  if (jobsArray != NULL) {
1684  bu_free(jobsArray, "dm-rtgl.c: jobsArray");
1685  jobsArray = NULL;
1686  }
1687  maxSpan = 0.0;
1688  rtgljob.numTrees = 0;
1689  numShot = rtgljob.numJobs = 0;
1690  rtgljob.currJob = NULL;
1691  numVisible = ged_build_tops(gedp, visibleTrees, &visibleTrees[visibleCount]);
1692  for (i = 0; i < numVisible; i++) {
1693  currTree = visibleTrees[i];
1694  new = 1;
1695 
1696  /* if this tree is in the old tree list, it's not new
1697  * if it's NOT in the old list, it needs to be cleared,
1698  * but that's not set up yet without clearing everything
1699  * first and starting over.
1700  **/
1701  for (j = 0; j < rtgljob.numTrees; j++) {
1702  if (BU_STR_EQUAL(currTree, rtgljob.oldTrees[j]))
1703  new = 0;
1704  }
1705 
1706  if (new) {
1707  /* will ray trace new tree*/
1708  if (rt_gettree(rtip, currTree) < 0)
1709  return TCL_ERROR;
1710 
1711  /* add new tree to list of displayed */
1712  numNew++;
1713  rtgl_stashTree(&rtgljob, currTree);
1714  }
1715  }
1716 
1717  }
1718 
1719  /* initialize job list */
1720  BU_LIST_INIT(&(jobs.l));
1721 
1722  BU_ALLOC(rtgljob.currJob, struct jobList);
1723  BU_LIST_PUSH(&(jobs.l), rtgljob.currJob);
1724  rtgljob.currJob->used = 0;
1725 
1726  /* set up application */
1727  RT_APPLICATION_INIT(&app);
1728  app.a_onehit = 0;
1730  app.a_hit = recordHit;
1731  app.a_miss = ignoreMiss;
1732  app.a_rt_i = rtip;
1733 
1734  /* prepare for ray tracing */
1735  rt_prep_parallel(rtip, 1);
1736 
1737  /* get min and max points of bounding box */
1738  VMOVE(min, rtip->mdl_min);
1739  VMOVE(max, rtip->mdl_max);
1740  VSUB2(span, max, min);
1741 
1742  maxSpan = span[X];
1743 
1744  if (span[Y] > maxSpan)
1745  maxSpan = span[Y];
1746 
1747  if (span[Z] > maxSpan)
1748  maxSpan = span[Z];
1749 
1750  /* create ray-trace jobs */
1751  shootGrid(&jobs, min, max, maxSpan, maxPixels, X, Y, Z);
1752  shootGrid(&jobs, min, max, maxSpan, maxPixels, Z, X, Y);
1753  shootGrid(&jobs, min, max, maxSpan, maxPixels, Y, Z, X);
1754 
1755  bu_log("firing %d jobs", rtgljob.numJobs);
1756 
1757  /* create job array */
1758  jobsArray = bu_malloc(sizeof(struct jobList *) * rtgljob.numJobs, "dm-rtgl.c: jobsArray");
1759 
1760  i = 0;
1761  for (BU_LIST_FOR_BACKWARDS(rtgljob.currJob, jobList, &(jobs.l))) {
1762  jobsArray[i++] = rtgljob.currJob;
1763  }
1764 
1765  start = time(NULL);
1766 
1767  shuffleJobs();
1768  /* new jobs to do */
1769  rtgljob.jobsDone = 0;
1770 
1771  } /* numNew > 0 */
1772 
1773  /* done with visibleTrees */
1774  if (visibleTrees != NULL) {
1775  bu_free(visibleTrees, "free visibleTrees");
1776  visibleTrees = NULL;
1777  }
1778 
1779  /* get view vector */
1780  bn_vec_aed(view, gedp->ged_gvp->gv_aet[0]*DEG2RAD, gedp->ged_gvp->gv_aet[1]*DEG2RAD, 1);
1781 
1782  if (difftime(time(NULL), start) > 3) {
1783 
1784  /* adjust point size based on zoom */
1785  size_t pointSize = 2;
1786 
1787  /* adjust point size based on % jobs completed */
1788  double p = (double) numShot / (double) rtgljob.numJobs;
1789 
1790  float fview[3];
1791  VMOVE(fview, view);
1792 
1793  if (maxSpan != 0.0) {
1794  double ratio = maxSpan / viewSize;
1795 
1796  pointSize = 2 * ratio;
1797 
1798  if (pointSize < 1)
1799  pointSize = 1;
1800  }
1801 
1802  pointSize = (size_t)rint((double)pointSize / p);
1803  if (pointSize > (maxPixels / 50)) {
1804  pointSize = maxPixels / 50;
1805  }
1806 
1807  drawPoints(fview, pointSize);
1808  }
1809 
1810  if (!rtgljob.jobsDone) {
1811  RTGL_DIRTY = 1;
1812 
1813  if ((rtgljob.jobsDone = shootJobs(&jobs))) {
1814  freeJobList(&jobs);
1815 
1816  if (jobsArray != NULL) {
1817  bu_free(jobsArray, "dm-rtgl.c: jobsArray");
1818  jobsArray = NULL;
1819  }
1820 
1821  RTGL_DIRTY = 0;
1822 
1823  numShot = rtgljob.numJobs = 0;
1824 
1825  bu_log("jobs done");
1826  }
1827  } else {
1828  RTGL_DIRTY = 0;
1829  }
1830 
1831  rtgljob.calls++;
1832 
1833  return TCL_OK;
1834 }
1835 
1836 
1837 HIDDEN int
1838 rtgl_draw(dm *dmp, struct bn_vlist *(*callback_function)(void *), void **data)
1839 {
1840  struct bn_vlist *vp;
1841  if (!callback_function) {
1842  if (data) {
1843  vp = (struct bn_vlist *)data;
1844  rtgl_drawVList(dmp, vp);
1845  }
1846  } else {
1847  if (!data) {
1848  return TCL_ERROR;
1849  } else {
1850  vp = callback_function(data);
1851  }
1852  }
1853  return TCL_OK;
1854 }
1855 
1856 
1857 /*
1858  * Restore the display processor to a normal mode of operation
1859  * (i.e., not scaled, rotated, displaced, etc.).
1860  */
1861 HIDDEN int
1862 rtgl_normal(dm *dmp)
1863 {
1864 
1865  if (dmp->dm_debugLevel)
1866  bu_log("rtgl_normal\n");
1867 
1868  if (!((struct rtgl_vars *)dmp->dm_vars.priv_vars)->face_flag) {
1869  glMatrixMode(GL_PROJECTION);
1870  glPushMatrix();
1871  glLoadMatrixd(((struct rtgl_vars *)dmp->dm_vars.priv_vars)->faceplate_mat);
1872  glMatrixMode(GL_MODELVIEW);
1873  glPushMatrix();
1874  glLoadIdentity();
1875  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->face_flag = 1;
1876  if (((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.cueing_on)
1877  glDisable(GL_FOG);
1878  if (dmp->dm_light)
1879  glDisable(GL_LIGHTING);
1880  }
1881 
1882  return TCL_OK;
1883 }
1884 
1885 
1886 /*
1887  * Output a string.
1888  * The starting position of the beam is as specified.
1889  */
1890 HIDDEN int
1891 rtgl_drawString2D(dm *dmp, const char *str, fastf_t x, fastf_t y, int UNUSED(size), int use_aspect)
1892 {
1893  if (!dmp)
1894  return TCL_ERROR;
1895 
1896  if (dmp->dm_debugLevel)
1897  bu_log("rtgl_drawString2D()\n");
1898 
1899  if (use_aspect)
1900  glRasterPos2f(x, y * dmp->dm_aspect);
1901  else
1902  glRasterPos2f(x, y);
1903 
1904  glListBase(((struct rtgl_vars *)dmp->dm_vars.priv_vars)->fontOffset);
1905  glCallLists(strlen(str), GL_UNSIGNED_BYTE, str);
1906 
1907  return TCL_OK;
1908 }
1909 
1910 
1911 HIDDEN int
1912 rtgl_drawLine2D(dm *dmp, fastf_t x1, fastf_t y1, fastf_t x2, fastf_t y2)
1913 {
1914 
1915  return drawLine2D(dmp, x1, y1, x2, y2, "rtgl_drawLine2D()\n");
1916 }
1917 
1918 
1919 HIDDEN int
1920 rtgl_drawLine3D(dm *dmp, point_t UNUSED(pt1), point_t UNUSED(pt2))
1921 {
1922  if (!dmp)
1923  return TCL_ERROR;
1924  return TCL_OK;
1925 }
1926 
1927 
1928 HIDDEN int
1929 rtgl_drawLines3D(dm *dmp, int npoints, point_t *points, int UNUSED(sflag))
1930 {
1931  if (!dmp || npoints < 0 || !points)
1932  return TCL_ERROR;
1933  return TCL_OK;
1934 }
1935 
1936 
1937 HIDDEN int
1938 rtgl_drawPoint2D(dm *dmp, fastf_t x, fastf_t y)
1939 {
1940  if (dmp->dm_debugLevel) {
1941  bu_log("rtgl_drawPoint2D():\n");
1942  bu_log("\tdmp: %lu\tx - %lf\ty - %lf\n", (unsigned long)dmp, x, y);
1943  }
1944 
1945  glBegin(GL_POINTS);
1946  glVertex2f(x, y);
1947  glEnd();
1948 
1949  return TCL_OK;
1950 }
1951 
1952 
1953 HIDDEN int
1954 rtgl_drawPoint3D(dm *dmp, point_t point)
1955 {
1956  if (!dmp || !point)
1957  return TCL_ERROR;
1958 
1959  if (dmp->dm_debugLevel) {
1960  bu_log("rtgl_drawPoint3D():\n");
1961  bu_log("\tdmp: %llu\tpt - %lf %lf %lf\n", (unsigned long long)dmp, V3ARGS(point));
1962  }
1963 
1964  glBegin(GL_POINTS);
1965  glVertex3dv(point);
1966  glEnd();
1967 
1968  return TCL_OK;
1969 }
1970 
1971 
1972 HIDDEN int
1973 rtgl_drawPoints3D(dm *dmp, int npoints, point_t *points)
1974 {
1975  register int i;
1976 
1977  if (!dmp || npoints < 0 || !points)
1978  return TCL_ERROR;
1979 
1980  if (dmp->dm_debugLevel) {
1981  bu_log("rtgl_drawPoint3D():\n");
1982  }
1983 
1984  glBegin(GL_POINTS);
1985  for (i = 0; i < npoints; ++i)
1986  glVertex3dv(points[i]);
1987  glEnd();
1988 
1989  return TCL_OK;
1990 }
1991 
1992 
1993 HIDDEN int
1994 rtgl_setFGColor(dm *dmp, unsigned char r, unsigned char g, unsigned char b, int strict, fastf_t transparency)
1995 {
1996  if (dmp->dm_debugLevel)
1997  bu_log("rtgl_setFGColor()\n");
1998 
1999  dmp->dm_fg[0] = r;
2000  dmp->dm_fg[1] = g;
2001  dmp->dm_fg[2] = b;
2002 
2003  if (strict) {
2004  glColor3ub((GLubyte)r, (GLubyte)g, (GLubyte)b);
2005  } else {
2006 
2007  if (dmp->dm_light) {
2008  /* Ambient = .2, Diffuse = .6, Specular = .2 */
2009 
2010  /* wireColor gets the full rgb */
2011  wireColor[0] = r / 255.0;
2012  wireColor[1] = g / 255.0;
2013  wireColor[2] = b / 255.0;
2014  wireColor[3] = transparency;
2015 
2016  ambientColor[0] = wireColor[0] * 0.2;
2017  ambientColor[1] = wireColor[1] * 0.2;
2018  ambientColor[2] = wireColor[2] * 0.2;
2019  ambientColor[3] = wireColor[3];
2020 
2021  specularColor[0] = ambientColor[0];
2022  specularColor[1] = ambientColor[1];
2023  specularColor[2] = ambientColor[2];
2024  specularColor[3] = ambientColor[3];
2025 
2026  diffuseColor[0] = wireColor[0] * 0.6;
2027  diffuseColor[1] = wireColor[1] * 0.6;
2028  diffuseColor[2] = wireColor[2] * 0.6;
2029  diffuseColor[3] = wireColor[3];
2030 
2031  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambientColor);
2032  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularColor);
2033  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuseColor);
2034 
2035  } else {
2036  glColor3ub((GLubyte)r, (GLubyte)g, (GLubyte)b);
2037  }
2038  }
2039 
2040  return TCL_OK;
2041 }
2042 
2043 
2044 HIDDEN int
2045 rtgl_setBGColor(dm *dmp, unsigned char r, unsigned char g, unsigned char b)
2046 {
2047  if (dmp->dm_debugLevel)
2048  bu_log("rtgl_setBGColor()\n");
2049 
2050  dmp->dm_bg[0] = r;
2051  dmp->dm_bg[1] = g;
2052  dmp->dm_bg[2] = b;
2053 
2054  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->r = r / 255.0;
2055  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->g = g / 255.0;
2056  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->b = b / 255.0;
2057 
2058  if (((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.doublebuffer) {
2059  if (!glXMakeCurrent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2060  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win,
2061  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc)) {
2062  bu_log("rtgl_setBGColor: Couldn't make context current\n");
2063  return TCL_ERROR;
2064  }
2065 
2066  glXSwapBuffers(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2067  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win);
2068  glClearColor(((struct rtgl_vars *)dmp->dm_vars.priv_vars)->r,
2069  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->g,
2070  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->b,
2071  0.0);
2072  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2073  }
2074 
2075  return TCL_OK;
2076 }
2077 
2078 
2079 HIDDEN int
2080 rtgl_setLineAttr(dm *dmp, int width, int style)
2081 {
2082  if (dmp->dm_debugLevel)
2083  bu_log("rtgl_setLineAttr()\n");
2084 
2085  dmp->dm_lineWidth = width;
2086  dmp->dm_lineStyle = style;
2087 
2088  glLineWidth((GLfloat) width);
2089 
2090  if (style == DM_DASHED_LINE)
2091  glEnable(GL_LINE_STIPPLE);
2092  else
2093  glDisable(GL_LINE_STIPPLE);
2094 
2095  return TCL_OK;
2096 }
2097 
2098 
2099 /* ARGSUSED */
2100 HIDDEN int
2101 rtgl_debug(dm *dmp, int lvl)
2102 {
2103  dmp->dm_debugLevel = lvl;
2104 
2105  return TCL_OK;
2106 }
2107 
2108 
2109 HIDDEN int
2110 rtgl_setWinBounds(dm *dmp, fastf_t *w)
2111 {
2112  if (dmp->dm_debugLevel)
2113  bu_log("rtgl_setWinBounds()\n");
2114 
2115  dmp->dm_clipmin[0] = w[0];
2116  dmp->dm_clipmin[1] = w[2];
2117  dmp->dm_clipmin[2] = w[4];
2118  dmp->dm_clipmax[0] = w[1];
2119  dmp->dm_clipmax[1] = w[3];
2120  dmp->dm_clipmax[2] = w[5];
2121 
2122  if (dmp->dm_clipmax[2] <= GED_MAX)
2123  dmp->dm_bound = 1.0;
2124  else
2125  dmp->dm_bound = GED_MAX / dmp->dm_clipmax[2];
2126 
2127  return TCL_OK;
2128 }
2129 
2130 
2131 #define RTGL_DO_STEREO 1
2132 /* currently, get a double buffered rgba visual that works with Tk and
2133  * OpenGL
2134  */
2135 HIDDEN XVisualInfo *
2136 rtgl_choose_visual(dm *dmp, Tk_Window tkwin)
2137 {
2138  XVisualInfo *vip, vitemp, *vibase, *maxvip;
2139 #define NGOOD 256
2140  int good[NGOOD];
2141  int tries, baddepth;
2142  int num, i, j;
2143  int fail;
2144 
2145  /* requirements */
2146  int screen;
2147  int use;
2148  int rgba;
2149  int dbfr;
2150 
2151  /* desires */
2152  int m_zbuffer = 1; /* m_zbuffer - try to get zbuffer */
2153  int zbuffer;
2154 #if RTGL_DO_STEREO
2155  int m_stereo; /* m_stereo - try to get stereo */
2156  int stereo;
2157 
2158  /*XXX Need to do something with this */
2159  if (dmp->dm_stereo) {
2160  m_stereo = 1;
2161  } else {
2162  m_stereo = 0;
2163  }
2164 #endif
2165 
2166  memset((void *)&vitemp, 0, sizeof(XVisualInfo));
2167  /* Try to satisfy the above desires with a color visual of the
2168  * greatest depth */
2169 
2170  vibase = XGetVisualInfo(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2171  0, &vitemp, &num);
2172  screen = DefaultScreen(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy);
2173 
2174  while (1) {
2175  for (i=0, j=0, vip=vibase; i<num; i++, vip++) {
2176  /* requirements */
2177  if (vip->screen != screen)
2178  continue;
2179 
2180  fail = glXGetConfig(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2181  vip, GLX_USE_GL, &use);
2182  if (fail || !use)
2183  continue;
2184 
2185  fail = glXGetConfig(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2186  vip, GLX_RGBA, &rgba);
2187  if (fail || !rgba)
2188  continue;
2189 
2190  fail = glXGetConfig(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2191  vip, GLX_DOUBLEBUFFER, &dbfr);
2192  if (fail || !dbfr)
2193  continue;
2194 
2195  /* desires */
2196  if (m_zbuffer) {
2197  fail = glXGetConfig(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2198  vip, GLX_DEPTH_SIZE, &zbuffer);
2199  if (fail || !zbuffer)
2200  continue;
2201  }
2202 
2203 #if RTGL_DO_STEREO
2204  if (m_stereo) {
2205  fail = glXGetConfig(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2206  vip, GLX_STEREO, &stereo);
2207  if (fail || !stereo) {
2208  bu_log("rtgl_choose_visual: failed visual - GLX_STEREO\n");
2209  continue;
2210  }
2211  }
2212 #endif
2213 
2214  /* this visual meets criteria */
2215  if (j >= NGOOD) {
2216  bu_log("rtgl_choose_visual: More than %d candidate visuals!\n", NGOOD);
2217  break;
2218  }
2219  good[j++] = i;
2220  }
2221 
2222  /* j = number of acceptable visuals under consideration */
2223  if (j >= 1) {
2224  baddepth = 1000;
2225  for (tries = 0; tries < j; ++tries) {
2226  maxvip = vibase + good[0];
2227  for (i=1; i<j; i++) {
2228  vip = vibase + good[i];
2229  if ((vip->depth > maxvip->depth)&&(vip->depth < baddepth)) {
2230  maxvip = vip;
2231  }
2232  }
2233 
2234  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->cmap =
2235  XCreateColormap(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2236  RootWindow(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2237  maxvip->screen), maxvip->visual, AllocNone);
2238 
2239  if (Tk_SetWindowVisual(tkwin,
2240  maxvip->visual, maxvip->depth,
2241  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->cmap)) {
2242 
2243  glXGetConfig(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2244  maxvip, GLX_DEPTH_SIZE,
2245  &((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.depth);
2246  if (((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.depth > 0)
2247  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.zbuf = 1;
2248 
2249  return maxvip; /* success */
2250  } else {
2251  /* retry with lesser depth */
2252  baddepth = maxvip->depth;
2253  XFreeColormap(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2254  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->cmap);
2255  }
2256  }
2257  }
2258 
2259  /* if no success at this point, relax a desire and try again */
2260 
2261 #if RTGL_DO_STEREO
2262  if (m_stereo) {
2263  m_stereo = 0;
2264  bu_log("Stereo not available.\n");
2265  continue;
2266  }
2267 #endif
2268 
2269  if (m_zbuffer) {
2270  m_zbuffer = 0;
2271  continue;
2272  }
2273 
2274  return (XVisualInfo *)NULL; /* failure */
2275  }
2276 }
2277 
2278 
2279 /**
2280  * Either initially, or on resize/reshape of the window, sense the
2281  * actual size of the window, and perform any other initializations of
2282  * the window configuration.
2283  *
2284  * also change font size if necessary
2285  */
2286 HIDDEN int
2287 rtgl_configureWin_guts(dm *dmp, int force)
2288 {
2289  GLint mm;
2290  XWindowAttributes xwa;
2291  XFontStruct *newfontstruct;
2292 
2293  if (dmp->dm_debugLevel)
2294  bu_log("rtgl_configureWin_guts()\n");
2295 
2296  if (!glXMakeCurrent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2297  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win,
2298  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc)) {
2299  bu_log("rtgl_configureWin_guts: Couldn't make context current\n");
2300  return TCL_ERROR;
2301  }
2302 
2303  XGetWindowAttributes(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2304  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win, &xwa);
2305 
2306  /* nothing to do */
2307  if (!force &&
2308  dmp->dm_height == xwa.height &&
2309  dmp->dm_width == xwa.width)
2310  return TCL_OK;
2311 
2312  dmp->dm_height = xwa.height;
2313  dmp->dm_width = xwa.width;
2314  dmp->dm_aspect = (fastf_t)dmp->dm_width / (fastf_t)dmp->dm_height;
2315 
2316  if (dmp->dm_debugLevel) {
2317  bu_log("rtgl_configureWin_guts()\n");
2318  bu_log("width = %d, height = %d\n", dmp->dm_width, dmp->dm_height);
2319  }
2320 
2321  glViewport(0, 0, dmp->dm_width, dmp->dm_height);
2322 
2323  if (dmp->dm_zbuffer)
2324  rtgl_setZBuffer(dmp, dmp->dm_zbuffer);
2325 
2326  rtgl_setLight(dmp, dmp->dm_light);
2327 
2328  glClearColor(((struct rtgl_vars *)dmp->dm_vars.priv_vars)->r,
2329  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->g,
2330  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->b,
2331  0.0);
2332  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2333 
2334  /*CJXX this might cause problems in perspective mode? */
2335  glGetIntegerv(GL_MATRIX_MODE, &mm);
2336  glMatrixMode(GL_PROJECTION);
2337  glLoadIdentity();
2338  glOrtho(-xlim_view, xlim_view, -ylim_view, ylim_view, 0.0, 2.0);
2339  glMatrixMode(mm);
2340 
2341  /* First time through, load a font or quit */
2342  if (((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct == NULL) {
2343  if ((((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct =
2344  XLoadQueryFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2345  FONT9)) == NULL) {
2346  /* Try hardcoded backup font */
2347  if ((((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct =
2348  XLoadQueryFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2349  FONTBACK)) == NULL) {
2350  bu_log("rtgl_configureWin_guts: Can't open font '%s' or '%s'\n", FONT9, FONTBACK);
2351  return TCL_ERROR;
2352  }
2353  }
2354  glXUseXFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct->fid,
2355  0, 127, ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->fontOffset);
2356  }
2357 
2358 
2359  /* Always try to choose a the font that best fits the window size.
2360  */
2361 
2362  if (dmp->dm_width < 582) {
2363  if (((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct->per_char->width != 5) {
2364  if ((newfontstruct = XLoadQueryFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2365  FONT5)) != NULL) {
2366  XFreeFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2367  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct);
2368  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct = newfontstruct;
2369  glXUseXFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct->fid,
2370  0, 127, ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->fontOffset);
2371  }
2372  }
2373  } else if (dmp->dm_width < 679) {
2374  if (((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct->per_char->width != 6) {
2375  if ((newfontstruct = XLoadQueryFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2376  FONT6)) != NULL) {
2377  XFreeFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2378  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct);
2379  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct = newfontstruct;
2380  glXUseXFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct->fid,
2381  0, 127, ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->fontOffset);
2382  }
2383  }
2384  } else if (dmp->dm_width < 776) {
2385  if (((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct->per_char->width != 7) {
2386  if ((newfontstruct = XLoadQueryFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2387  FONT7)) != NULL) {
2388  XFreeFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2389  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct);
2390  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct = newfontstruct;
2391  glXUseXFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct->fid,
2392  0, 127, ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->fontOffset);
2393  }
2394  }
2395  } else if (dmp->dm_width < 873) {
2396  if (((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct->per_char->width != 8) {
2397  if ((newfontstruct = XLoadQueryFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2398  FONT8)) != NULL) {
2399  XFreeFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2400  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct);
2401  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct = newfontstruct;
2402  glXUseXFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct->fid,
2403  0, 127, ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->fontOffset);
2404  }
2405  }
2406  } else {
2407  if (((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct->per_char->width != 9) {
2408  if ((newfontstruct = XLoadQueryFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2409  FONT9)) != NULL) {
2410  XFreeFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2411  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct);
2412  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct = newfontstruct;
2413  glXUseXFont(((struct dm_xvars *)dmp->dm_vars.pub_vars)->fontstruct->fid,
2414  0, 127, ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->fontOffset);
2415  }
2416  }
2417  }
2418 
2419  return TCL_OK;
2420 }
2421 
2422 
2423 HIDDEN int
2424 rtgl_configureWin(dm *dmp, int force)
2425 {
2426  return rtgl_configureWin_guts(dmp, force);
2427 }
2428 
2429 
2430 HIDDEN int
2431 rtgl_setLight(dm *dmp, int lighting_on)
2432 {
2433  if (dmp->dm_debugLevel)
2434  bu_log("rtgl_setLight()\n");
2435 
2436  dmp->dm_light = lighting_on;
2437  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.lighting_on = dmp->dm_light;
2438 
2439  if (!glXMakeCurrent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2440  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win,
2441  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc)) {
2442  bu_log("rtgl_setLight: Couldn't make context current\n");
2443  return TCL_ERROR;
2444  }
2445 
2446  if (!dmp->dm_light) {
2447  /* Turn it off */
2448  glDisable(GL_LIGHTING);
2449  } else {
2450  /* Turn it on */
2451 
2452  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb_three);
2453  glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
2454 
2455  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
2456  glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
2457  glLightfv(GL_LIGHT0, GL_SPECULAR, light0_diffuse);
2458 
2459  glEnable(GL_LIGHTING);
2460  glEnable(GL_LIGHT0);
2461  }
2462 
2463  return TCL_OK;
2464 }
2465 
2466 
2467 HIDDEN int
2468 rtgl_setTransparency(dm *dmp,
2469  int transparency_on)
2470 {
2471  if (dmp->dm_debugLevel)
2472  bu_log("rtgl_setTransparency()\n");
2473 
2474  dmp->dm_transparency = transparency_on;
2475  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.transparency_on = dmp->dm_transparency;
2476 
2477  if (!glXMakeCurrent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2478  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win,
2479  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc)) {
2480  bu_log("rtgl_setTransparency: Couldn't make context current\n");
2481  return TCL_ERROR;
2482  }
2483 
2484  if (transparency_on) {
2485  /* Turn it on */
2486  glEnable(GL_BLEND);
2487  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2488  } else {
2489  /* Turn it off */
2490  glDisable(GL_BLEND);
2491  }
2492 
2493  return TCL_OK;
2494 }
2495 
2496 
2497 HIDDEN int
2498 rtgl_setDepthMask(dm *dmp,
2499  int enable) {
2500  if (dmp->dm_debugLevel)
2501  bu_log("rtgl_setDepthMask()\n");
2502 
2503  dmp->dm_depthMask = enable;
2504 
2505  if (!glXMakeCurrent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2506  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win,
2507  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc)) {
2508  bu_log("rtgl_setDepthMask: Couldn't make context current\n");
2509  return TCL_ERROR;
2510  }
2511 
2512  if (enable)
2513  glDepthMask(GL_TRUE);
2514  else
2515  glDepthMask(GL_FALSE);
2516 
2517  return TCL_OK;
2518 }
2519 
2520 
2521 HIDDEN int
2522 rtgl_setZBuffer(dm *dmp, int zbuffer_on)
2523 {
2524  if (dmp->dm_debugLevel)
2525  bu_log("rtgl_setZBuffer:\n");
2526 
2527  dmp->dm_zbuffer = zbuffer_on;
2528  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.zbuffer_on = dmp->dm_zbuffer;
2529 
2530  if (!glXMakeCurrent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2531  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win,
2532  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc)) {
2533  bu_log("rtgl_setZBuffer: Couldn't make context current\n");
2534  return TCL_ERROR;
2535  }
2536 
2537  if (((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.zbuf == 0) {
2538  dmp->dm_zbuffer = 0;
2539  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.zbuffer_on = dmp->dm_zbuffer;
2540  }
2541 
2542  if (((struct rtgl_vars *)dmp->dm_vars.priv_vars)->mvars.zbuffer_on) {
2543  glDepthFunc(GL_LEQUAL);
2544  glEnable(GL_DEPTH_TEST);
2545  } else {
2546  glDisable(GL_DEPTH_TEST);
2547  }
2548 
2549  return TCL_OK;
2550 }
2551 
2552 
2553 int
2554 rtgl_beginDList(dm *dmp, unsigned int list)
2555 {
2556  if (dmp->dm_debugLevel)
2557  bu_log("rtgl_beginDList()\n");
2558 
2559  if (!glXMakeCurrent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2560  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win,
2561  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc)) {
2562  bu_log("rtgl_beginDList: Couldn't make context current\n");
2563  return TCL_ERROR;
2564  }
2565 
2566  glNewList((GLuint)list, GL_COMPILE);
2567  return TCL_OK;
2568 }
2569 
2570 
2571 int
2572 rtgl_endDList(dm *dmp)
2573 {
2574  if (dmp->dm_debugLevel)
2575  bu_log("rtgl_endDList()\n");
2576 
2577  glEndList();
2578  return TCL_OK;
2579 }
2580 
2581 
2582 void
2583 rtgl_drawDList(dm *dmp, unsigned int list)
2584 {
2585  glCallList((GLuint)list);
2586 }
2587 
2588 
2589 int
2590 rtgl_freeDLists(dm *dmp, unsigned int list, int range)
2591 {
2592  if (dmp->dm_debugLevel)
2593  bu_log("rtgl_freeDLists()\n");
2594 
2595  if (!glXMakeCurrent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2596  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win,
2597  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc)) {
2598  bu_log("rtgl_freeDLists: Couldn't make context current\n");
2599  return TCL_ERROR;
2600  }
2601 
2602  glDeleteLists((GLuint)list, (GLsizei)range);
2603  return TCL_OK;
2604 }
2605 
2606 
2607 int
2608 rtgl_genDLists(dm *dmp, size_t range)
2609 {
2610  if (dmp->dm_debugLevel)
2611  bu_log("rtgl_freeDLists()\n");
2612 
2613  if (!glXMakeCurrent(((struct dm_xvars *)dmp->dm_vars.pub_vars)->dpy,
2614  ((struct dm_xvars *)dmp->dm_vars.pub_vars)->win,
2615  ((struct rtgl_vars *)dmp->dm_vars.priv_vars)->glxc)) {
2616  bu_log("rtgl_freeDLists: Couldn't make context current\n");
2617  return TCL_ERROR;
2618  }
2619 
2620  return glGenLists((GLsizei)range);
2621 }
2622 
2623 int
2624 rtgl_openFb(struct dm_internal *dmp)
2625 {
2626  struct fb_platform_specific *fb_ps;
2627  struct ogl_fb_info *ofb_ps;
2628  struct modifiable_ogl_vars *mvars = (struct modifiable_ogl_vars *)dmp->m_vars;
2629  struct dm_xvars *pubvars = (struct dm_xvars *)dmp->dm_vars.pub_vars;
2630  struct ogl_vars *privars = (struct ogl_vars *)dmp->dm_vars.priv_vars;
2631 
2633  ofb_ps = (struct ogl_fb_info *)fb_ps->data;
2634  ofb_ps->dpy = pubvars->dpy;
2635  ofb_ps->win = pubvars->win;
2636  ofb_ps->cmap = pubvars->cmap;
2637  ofb_ps->vip = pubvars->vip;
2638  ofb_ps->glxc = privars->glxc;
2639  ofb_ps->double_buffer = mvars->doublebuffer;
2640 
2641  ofb_ps->soft_cmap = 0;
2642  dmp->fbp = fb_open_existing("ogl", dm_get_width(dmp), dm_get_height(dmp), fb_ps);
2643  fb_put_platform_specific(fb_ps);
2644  return 0;
2645 }
2646 
2647 dm dm_rtgl = {
2648  rtgl_close,
2649  rtgl_drawBegin,
2650  rtgl_drawEnd,
2651  rtgl_normal,
2652  rtgl_loadMatrix,
2654  rtgl_drawString2D,
2655  rtgl_drawLine2D,
2656  rtgl_drawLine3D,
2657  rtgl_drawLines3D,
2658  rtgl_drawPoint2D,
2659  rtgl_drawPoint3D,
2660  rtgl_drawPoints3D,
2661  rtgl_drawVList,
2662  rtgl_drawVList,
2663  rtgl_draw,
2664  rtgl_setFGColor,
2665  rtgl_setBGColor,
2666  rtgl_setLineAttr,
2667  rtgl_configureWin,
2668  rtgl_setWinBounds,
2669  rtgl_setLight,
2670  rtgl_setTransparency,
2671  rtgl_setDepthMask,
2672  rtgl_setZBuffer,
2673  rtgl_debug,
2674  rtgl_beginDList,
2675  rtgl_endDList,
2676  rtgl_drawDList,
2677  rtgl_freeDLists,
2678  rtgl_genDLists,
2679  NULL,
2680  null_getDisplayImage, /* display to image function */
2681  null_reshape,
2683  rtgl_openFb,
2684  NULL,
2685  NULL,
2686  0,
2687  1, /* has displaylist */
2688  0, /* no stereo by default */
2689  1.0, /* zoom-in limit, */
2690  1, /* bound flag */
2691  "rtgl",
2692  "X Windows with OpenGL graphics",
2693  DM_TYPE_RTGL,
2694  1,
2695  0,
2696  0,
2697  0, /* bytes per pixel */
2698  0, /* bits per channel */
2699  0,
2700  0,
2701  1.0, /* aspect ratio */
2702  0,
2703  {0, 0},
2704  NULL,
2705  NULL,
2706  BU_VLS_INIT_ZERO, /* bu_vls path name*/
2707  BU_VLS_INIT_ZERO, /* bu_vls full name drawing window */
2708  BU_VLS_INIT_ZERO, /* bu_vls short name drawing window */
2709  {0, 0, 0}, /* bg color */
2710  {0, 0, 0}, /* fg color */
2711  {GED_MIN, GED_MIN, GED_MIN}, /* clipmin */
2712  {GED_MAX, GED_MAX, GED_MAX}, /* clipmax */
2713  0, /* no debugging */
2714  BU_VLS_INIT_ZERO, /* bu_vls logfile */
2715  0, /* no perspective */
2716  0, /* no lighting */
2717  0, /* no transparency */
2718  1, /* depth buffer is writable */
2719  1, /* zbuffer */
2720  0, /* no zclipping */
2721  0, /* clear back buffer after drawing and swap */
2722  0, /* not overriding the auto font size */
2724  FB_NULL,
2725  0 /* Tcl interpreter */
2726 };
2727 
2728 
2729 #endif /* DM_RTGL */
2730 
2731 /*
2732  * Local Variables:
2733  * mode: C
2734  * tab-width: 8
2735  * indent-tabs-mode: t
2736  * c-file-style: "stroustrup"
2737  * End:
2738  * ex: shiftwidth=4 tabstop=8
2739  */
#define FONT5
Definition: dm.h:75
struct bu_list l
Definition: dm-rtgl.h:104
void bu_vls_init(struct bu_vls *vp)
Definition: vls.c:56
struct xray a_ray
Actual ray to be shot.
Definition: raytrace.h:1583
struct jobList * currJob
Definition: dm-rtgl.h:144
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
Definition: raytrace.h:800
#define GED_MAX
Definition: ged.h:253
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
GLXContext glxc
Definition: dm-ogl.h:47
struct region * pt_regionp
ptr to containing region
Definition: raytrace.h:580
struct hit * pt_outhit
OUT hit ptr.
Definition: raytrace.h:579
int dm_top
!0 means toplevel window
Definition: dm_private.h:90
unsigned char * bu_get_hash_value(const struct bu_hash_entry *hsh_entry)
Definition: hash.c:170
float norms[PT_ARRAY_SIZE]
Definition: dm-rtgl.h:107
int dm_width
Definition: dm_private.h:91
struct ptInfoList * currItem
Definition: dm-rtgl.h:143
Definition: list.h:118
point_t mdl_min
min corner of model bounding RPP
Definition: raytrace.h:1769
void * pub_vars
Definition: dm_private.h:35
ustring interp
#define DM_DASHED_LINE
Definition: dm.h:109
int dm_zclip
!0 means zclipping
Definition: dm_private.h:116
void * data
Definition: fb.h:176
fb * fbp
Framebuffer associated with this display instance.
Definition: dm_private.h:120
GLclampf g
Definition: dm-rtgl.h:76
Definition: dm-rtgl.h:84
int dm_displaylist
!0 means device has displaylist
Definition: dm_private.h:83
int dm_get_width(dm *dmp)
Definition: dm-generic.c:335
#define RT_CK_APPLICATION(_p)
Definition: raytrace.h:1675
void rt_silent_logoverlap(struct application *ap, const struct partition *pp, const struct bu_ptbl *regiontable, const struct partition *InputHdp)
Definition: bool.c:1122
void bu_hash_tbl_free(struct bu_hash_tbl *hsh_tbl)
Definition: hash.c:263
Definition: ged.h:338
#define COPY_JOB(a, b)
Definition: dm-rtgl.h:95
struct db_i * dbip
Definition: raytrace.h:1266
struct soltab * seg_stp
pointer back to soltab
Definition: raytrace.h:372
size_t ged_count_tops(struct ged *gedp)
Definition: rt.c:409
dm dm_rtgl
#define FB_OGL_MAGIC
Definition: magic.h:182
#define FONT9
Definition: dm.h:79
vect_t dm_clipmax
maximum clipping vector
Definition: dm_private.h:108
Definition: raytrace.h:368
Tcl_Interp * dm_interp
Tcl interpreter.
Definition: dm_private.h:121
void bu_set_hash_value(struct bu_hash_entry *hsh_entry, unsigned char *value)
Definition: hash.c:160
unsigned char dm_fg[3]
foreground color
Definition: dm_private.h:106
int dm_processOptions(dm *dmp, struct bu_vls *init_proc_vls, int argc, char **argv)
Definition: options.c:38
struct bu_hash_entry * bu_hash_tbl_first(const struct bu_hash_tbl *hsh_tbl, struct bu_hash_record *rec)
Definition: hash.c:296
GLclampf r
Definition: dm-rtgl.h:76
Definition: raytrace.h:248
#define FONT6
Definition: dm.h:76
void bu_vls_strncpy(struct bu_vls *vp, const char *s, size_t n)
Definition: vls.c:339
char pt_inflip
flip inhit->hit_normal
Definition: raytrace.h:581
size_t numTrees
Definition: dm-rtgl.h:140
long Display
Definition: dm_xvars.h:49
struct rt_wdb * ged_wdbp
Definition: ged.h:340
Header file for the BRL-CAD common definitions.
int null_loadPMatrix(struct dm_internal *dmp, fastf_t *mat)
Definition: dm-Null.c:73
long time(time_t *)
struct bu_hash_tbl * colorTable
Definition: dm-rtgl.h:142
char pt_outflip
flip outhit->hit_normal
Definition: raytrace.h:582
Definition: hash.h:44
int dm_light
!0 means lighting on
Definition: dm_private.h:112
char ft_label[9]
Definition: raytrace.h:2044
int a_onehit
flag to stop on first hit
Definition: raytrace.h:1586
int calls
Definition: dm-rtgl.h:137
ustring width
GLXContext glxc
Definition: dm-rtgl.h:69
int(* a_hit)(struct application *, struct partition *, struct seg *)
called when shot hits model
Definition: raytrace.h:1584
fastf_t dm_aspect
Definition: dm_private.h:97
struct hit * pt_inhit
IN hit pointer.
Definition: raytrace.h:577
#define HIDDEN
Definition: common.h:86
struct fb_platform_specific * fb_get_platform_specific(uint32_t magic)
Definition: fb_generic.c:113
#define RTI_NULL
Definition: raytrace.h:1830
struct bview * ged_gvp
Definition: ged.h:361
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
int dm_clearBufferAfter
1 means clear back buffer after drawing and swap
Definition: dm_private.h:117
double rt_get_timer(struct bu_vls *vp, double *elapsed)
Definition: timer-nt.c:44
struct bu_vls dm_tkName
short Tcl/Tk name of drawing window
Definition: dm_private.h:103
#define DM_TYPE_RTGL
Definition: dm.h:101
if(share_geom)
Definition: nmg_mod.c:3829
fastf_t * dm_vp
(FIXME: ogl still depends on this) Viewscale pointer
Definition: dm_private.h:98
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
int bu_strncmp(const char *string1, const char *string2, size_t n)
Definition: str.c:191
Definition: color.c:49
COMPLEX data[64]
Definition: fftest.c:34
struct rt_i * a_rt_i
this librt instance
Definition: raytrace.h:1588
#define DM_NULL
Definition: dm.h:43
void * memset(void *s, int c, size_t n)
size_t numJobs
Definition: dm-rtgl.h:145
#define RTGL_MVARS
Definition: dm-rtgl.h:45
int drawLine2D(struct dm_internal *dmp, fastf_t X1, fastf_t Y1, fastf_t X2, fastf_t Y2, const char *log_bu)
#define FB_NULL
Definition: fb.h:95
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
int dm_perspective
!0 means perspective on
Definition: dm_private.h:111
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
fastf_t gv_isize
1.0 / size
Definition: bview.h:213
unsigned long dm_id
window id
Definition: dm_private.h:82
#define START_TABLE_SIZE
Definition: dm-rtgl.h:99
#define BU_LIST_FOR_BACKWARDS(p, structure, hp)
Definition: list.h:370
int rtglWasClosed
Definition: dm-rtgl.h:146
int used
Definition: dm-rtgl.h:91
int null_makeCurrent(struct dm_internal *dmp)
Definition: dm-Null.c:272
#define V3ARGS(a)
Definition: color.c:56
fastf_t gv_size
2.0 * scale
Definition: bview.h:212
struct bu_list * back
"back", "last"
Definition: list.h:121
struct bu_vls dm_dName
Display name.
Definition: dm_private.h:104
struct seg * pt_inseg
IN seg ptr (gives stp)
Definition: raytrace.h:576
float points[PT_ARRAY_SIZE]
Definition: dm-rtgl.h:106
int vectorThreshold
Definition: tcl.c:46
struct ptInfoList * list
Definition: dm-rtgl.h:112
Coord * point
Definition: chull3d.cpp:52
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
#define RTGL_GEDP
Definition: dm-rtgl.h:46
#define GED_NULL
Definition: ged.h:72
void * bu_realloc(void *ptr, size_t siz, const char *str)
#define UNUSED(parameter)
Definition: common.h:239
struct bu_hash_entry * bu_hash_tbl_add(struct bu_hash_tbl *hsh_tbl, const unsigned char *key, int key_len, int *new_entry)
Definition: hash.c:188
#define GED_MIN
Definition: ged.h:254
void bn_mat_mul(mat_t o, const mat_t a, const mat_t b)
#define FONT7
Definition: dm.h:77
vect_t dir
Definition: dm-rtgl.h:86
int dm_get_height(dm *dmp)
Definition: dm-generic.c:342
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
#define BU_LIST_WHILE(p, structure, hp)
Definition: list.h:410
int dm_stereo
stereo flag
Definition: dm_private.h:84
int dm_lineWidth
Definition: dm_private.h:95
void null_reshape(struct dm_internal *dmp, int width, int height)
Definition: dm-Null.c:266
#define HIDDEN_DM_FUNCTION_PROTOTYPES(_dmtype)
Definition: dm_private.h:151
#define KEY_LENGTH
Definition: dm-rtgl.h:100
vect_t r_dir
Direction of ray (UNIT Length)
Definition: raytrace.h:219
#define BU_STRUCTPARSE_NULL
Definition: parse.h:151
int used
Definition: dm-rtgl.h:105
void * Tk_Window
Definition: dm_xvars.h:44
float ma_color[3]
explicit color: 0..1
Definition: raytrace.h:522
struct rt_i * rt_new_rti(struct db_i *dbip)
Definition: prep.c:58
char ** oldTrees
Definition: dm-rtgl.h:139
int rt_gettree(struct rt_i *rtip, const char *node)
Definition: tree.c:869
#define BU_LIST_PUSH(hp, p)
Definition: list.h:246
#define FONT8
Definition: dm.h:78
fb * fb_open_existing(const char *file, int _width, int _height, struct fb_platform_specific *fb_p)
Definition: fb_generic.c:146
size_t treeCapacity
Definition: dm-rtgl.h:141
struct mater_info reg_mater
Real material information.
Definition: raytrace.h:546
#define BU_LIST_INIT(_hp)
Definition: list.h:148
void bn_vec_aed(vect_t vec, fastf_t az, fastf_t el, fastf_t dist)
Definition: mat.c:446
void(* a_logoverlap)(struct application *, const struct partition *, const struct bu_ptbl *, const struct partition *)
called to log overlaps
Definition: raytrace.h:1594
point_t r_pt
Point at which ray starts.
Definition: raytrace.h:218
struct bu_hash_entry * bu_hash_tbl_next(struct bu_hash_record *rec)
Definition: hash.c:327
void * priv_vars
Definition: dm_private.h:36
vect_t dm_clipmin
minimum clipping vector
Definition: dm_private.h:107
Definition: vlist.h:71
point_t pt
Definition: dm-rtgl.h:85
void rtgl_fogHint()
#define DBI_NULL
Definition: raytrace.h:827
struct dm_vars dm_vars
display manager dependent variables
Definition: dm_private.h:99
int controlClip
Definition: dm-rtgl.h:136
int dm_height
Definition: dm_private.h:92
HIDDEN fastf_t bin(fastf_t val, fastf_t step)
Definition: nmg_tri_mc.c:461
point_t mdl_max
max corner of model bounding RPP
Definition: raytrace.h:1770
int dm_zbuffer
!0 means zbuffer on
Definition: dm_private.h:115
int clip(fastf_t *, fastf_t *, fastf_t *, fastf_t *)
Definition: clip.c:66
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
struct bu_vls dm_pathName
full Tcl/Tk name of drawing window
Definition: dm_private.h:102
#define FONTBACK
Definition: dm.h:74
int jobsDone
Definition: dm-rtgl.h:138
double dm_bound
zoom-in limit
Definition: dm_private.h:85
unsigned char dm_bg[3]
background color
Definition: dm_private.h:105
Definition: color.c:51
#define BU_LIST_NULL
Definition: list.h:124
void rt_prep_parallel(struct rt_i *rtip, int ncpu)
int rt_shootray(struct application *ap)
void bu_vls_strcpy(struct bu_vls *vp, const char *s)
Definition: vls.c:310
vect_t gv_aet
Definition: bview.h:215
int hit_surfno
solid-specific surface indicator
Definition: raytrace.h:255
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
int null_getDisplayImage(struct dm_internal *dmp, unsigned char **image)
Definition: dm-Null.c:259
int dm_transparency
!0 means transparency on
Definition: dm_private.h:113
int(* a_miss)(struct application *)
called when shot misses
Definition: raytrace.h:1585
void * m_vars
Definition: dm_private.h:100
struct modifiable_rtgl_vars mvars
Definition: dm-rtgl.h:77
const struct rt_functab * st_meth
pointer to per-solid methods
Definition: raytrace.h:428
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
#define RT_HIT_NORMAL(_normal, _hitp, _stp, _unused, _flipflag)
Definition: raytrace.h:273
float color[3]
Definition: dm-rtgl.h:111
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
struct bu_list * forw
"forward", "next"
Definition: list.h:120
struct partition * pt_forw
forwards link
Definition: raytrace.h:574
struct bu_hash_tbl * bu_hash_tbl_create(unsigned long tbl_size)
Definition: hash.c:48
#define RT_APPLICATION_INIT(_p)
Definition: raytrace.h:1676
int dm_boundFlag
Definition: dm_private.h:86
fastf_t hit_dist
dist from r_pt to hit_point
Definition: raytrace.h:250
int dm_debugLevel
!0 means debugging
Definition: dm_private.h:109
struct bu_hash_entry * bu_hash_tbl_find(const struct bu_hash_tbl *hsh_tbl, const unsigned char *key, int key_len, struct bu_hash_entry **prev, unsigned long *idx)
Definition: hash.c:95
Definition: vls.h:56
#define PT_ARRAY_SIZE
Definition: dm-rtgl.h:101
struct bu_hash_entry * next
Definition: hash.h:49
double fastf_t
Definition: defines.h:300
GLclampf b
Definition: dm-rtgl.h:76
struct job jobs[JOB_ARRAY_SIZE]
Definition: dm-rtgl.h:92
int dm_lineStyle
Definition: dm_private.h:96
int ged_build_tops(struct ged *gedp, char **start, char **end)
Definition: rt.c:424
#define JOB_ARRAY_SIZE
Definition: dm-rtgl.h:82
Definition: color.c:50
void fb_put_platform_specific(struct fb_platform_specific *fb_p)
Definition: fb_generic.c:129
int dm_depthMask
!0 means depth buffer is writable
Definition: dm_private.h:114
#define RTGL_DIRTY
Definition: dm-rtgl.h:47
struct bu_list l
Definition: dm-rtgl.h:90
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126