ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/lsys/gl_int.cpp
Revision: 1.1
Committed: Thu Nov 6 14:31:24 2008 UTC (15 years, 6 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2     * opengl interface
3     */
4    
5     #include "config.h"
6    
7     #if HAVE_OPENGL
8    
9     #include <GL/glx.h>
10     #include <GL/glu.h>
11     #include <X11/keysym.h>
12    
13     #include <iostream>
14     #include <iomanip>
15     #include <cmath>
16     #include <cstdlib>
17    
18     #include "interface.h"
19     #include "gl_int.h"
20    
21     inline void glVertex (const vec &v) { glVertex3d (v[0], v[1], v[2]); }
22     inline void glNormal (const vec &v) { glNormal3d (v[0], v[1], v[2]); }
23    
24     #define Begin(m) glBegin(m); in_begin = true;
25     #define End() glEnd(); in_begin = false;
26    
27     #define HW_ACCUM 1
28     //#undef HW_ACCUM
29    
30     gl_int::gl_int () t_no
31     {
32     in_begin = false;
33    
34     dpy = XOpenDisplay (0);
35     if (!dpy)
36     throw error("can't open display");
37    
38     int attributeList[] = {
39     GLX_RGBA,
40     GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1,
41     #if HW_ACCUM
42     GLX_ACCUM_RED_SIZE, 1, GLX_ACCUM_GREEN_SIZE, 1, GLX_ACCUM_BLUE_SIZE, 1,
43     #endif
44     None };
45    
46     vi = glXChooseVisual (dpy, DefaultScreen(dpy), attributeList);
47     if (!vi) error("no suitable visual");
48    
49     glXGetConfig (dpy, vi, GLX_ALPHA_SIZE, &fb_depth);
50     if (fb_depth > 0)
51     {
52     fb_format = GL_RGBA;
53     fb_depth = 4;
54     }
55     else
56     {
57     fb_format = GL_RGB;
58     fb_depth = 3;
59     }
60    
61     cx = glXCreateContext (dpy, vi, 0, GL_TRUE);
62    
63     swa.colormap = XCreateColormap (dpy, RootWindow(dpy, vi->screen),
64     vi->visual, AllocNone);
65    
66     swa.border_pixel = 0;
67     swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
68     ButtonPressMask | ButtonReleaseMask | ButtonMotionMask;
69     win = XCreateWindow (dpy, RootWindow (dpy, vi->screen), 0, 0, 900, 900,
70     0, vi->depth, InputOutput, vi->visual,
71     CWBorderPixel | CWColormap | CWEventMask, &swa);
72     XStoreName (dpy, win, PACKAGE " - " VERSION);
73     XMapWindow (dpy, win);
74    
75     glXMakeCurrent(dpy, win, cx);
76    
77     /* set up viewing parameters */
78     glMatrixMode (GL_PROJECTION);
79     gluPerspective (20, 1, 0.1, 20);
80     glMatrixMode (GL_MODELVIEW);
81     glTranslatef (0, 0, -15);
82    
83     /* set other relevant state information */
84     glEnable (GL_DEPTH_TEST);
85     //glEnable (GL_AUTO_NORMAL);
86     //glEnable (GL_DITHER);
87     //glEnable (GL_LINE_SMOOTH);
88     //glEnable (GL_POLYGON_SMOOTH);
89    
90     float specular[] = {1.0, 1.0, 1.0, 1.0};
91     float diffuse[] = {0.7, 0.7, 0.7, 0.7};
92     float position0[] = {0.2, -1.0, 0.2, 0.0};
93     float position1[] = {0.0, -1.0, -1.0, 0.0};
94     float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
95     float local_view[] = { 0.0 };
96    
97     glLightModelfv (GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
98     glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
99     glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
100     glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuse);
101     glLightfv (GL_LIGHT0, GL_POSITION, position0);
102     glLightfv (GL_LIGHT1, GL_DIFFUSE, diffuse);
103     glLightfv (GL_LIGHT1, GL_POSITION, position1);
104     glEnable (GL_LIGHT0);
105     //glEnable (GL_LIGHT1);
106     glEnable (GL_LIGHTING);
107    
108     glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
109     glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
110    
111     glEnable (GL_NORMALIZE);
112    
113     glShadeModel (GL_SMOOTH);
114     glEnable (GL_POLYGON_OFFSET_FILL);
115     glPolygonOffset (-1, -1);
116    
117     glClearColor (1.0, 1.0, 1.0, 0.0);
118    
119     float spec[] = { 0.7, 0.7, 0.7, 0.0 }; glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec);
120     float shine[] = { 20.0 }; glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, shine);
121     float diff[] = { 0.4, 0.4, 0.4, 1.0 }; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, diff);
122     }
123    
124     gl_int::~gl_int () t_no
125     {
126     XCloseDisplay (dpy);
127     }
128    
129     #define TREE_LIST 1
130    
131     void gl_int::begin_fig () t_no
132     {
133     x1 = 1e10; y1 = 1e10; z1 = 1e10;
134     x2 = -1e10; y2 = -1e10; z2 = -1e10;
135     glNewList (TREE_LIST, GL_COMPILE);
136     }
137    
138     void gl_int::end_fig () t_no
139     {
140     XEvent event;
141     static int prevx, prevy;
142     static int deltax = 0, deltay = 0;
143    
144     x1 -= 0.1; y1 -= 0.1; z1 -= 0.1;
145     x2 += 0.1; y2 += 0.1; z2 += 0.2;
146     glEndList ();
147    
148     bool changed = true;
149     const bool hwaccum = false; // hwaccum does not work
150    
151     // the following are only initialized to prevent a compiler warning
152     double xoffset = -1;
153     double yoffset = -1;
154     double stepsize = -1;
155     bool even = false;
156     double weight = -1;
157    
158     bool antialias = false;
159     static bool buttondown = false;
160    
161     static unsigned long vX, vY, vW, vH, wW, wH, wWHD; // must(!) be static
162    
163     // swaccum
164     typedef unsigned char pix_t;
165     typedef unsigned long acc_t;
166     const int acc_scale = 1 << 24;
167     pix_t *pixbuf = 0; // read pixel buffer
168     acc_t *accumbuf = 0; // our accumbuf
169     acc_t accsum;
170    
171     for (bool loop = true; loop; )
172     {
173     antialias = antialias || !buttondown;
174    
175     if (buttondown || !antialias || XPending (dpy))
176     do
177     {
178     char buf[31];
179     KeySym keysym;
180    
181     XNextEvent (dpy, &event);
182     switch (event.type)
183     {
184     case Expose:
185     break;
186    
187     case ConfigureNotify:
188     {
189     /* this approach preserves a 1:1 viewport aspect ratio */
190     int eW = event.xconfigure.width, eH = event.xconfigure.height;
191    
192     eW = eW & ~3; // for alignment purposes
193    
194     if (eW != wW || eH != wH)
195     {
196     changed = true;
197     wW = eW; wH = eH;
198     wWHD = wW * wH * fb_depth;
199    
200     if (eW >= eH)
201     {
202     vX = 0;
203     vY = (eH - eW) >> 1;
204     vW = vH = eW;
205     }
206     else
207     {
208     vX = (eW - eH) >> 1;
209     vY = 0;
210     vW = vH = eH;
211     }
212    
213     glViewport (vX, vY, vW, vH);
214     }
215     }
216     break;
217    
218     case KeyPress:
219     (void) XLookupString (&event.xkey, buf, sizeof (buf), &keysym, NULL);
220     switch (keysym)
221     {
222     case XK_a:
223     antialias = true;
224     break;
225     case XK_q:
226     case XK_Escape:
227     loop = false;
228     break;
229     default:
230     break;
231     }
232     break;
233    
234     case ButtonPress:
235     prevx = event.xbutton.x;
236     prevy = event.xbutton.y;
237     buttondown = true;
238     break;
239    
240     case ButtonRelease:
241     buttondown = false;
242     break;
243    
244     case MotionNotify:
245     deltax += (event.xbutton.x - prevx);
246     prevx = event.xbutton.x;
247     deltay += (event.xbutton.y - prevy);
248     prevy = event.xbutton.y;
249     changed = true;
250     break;
251    
252     default:
253     break;
254     }
255     }
256     while (XPending (dpy));
257    
258     if (changed || buttondown)
259     {
260     changed = false;
261     stepsize = 2;
262     xoffset = 0;
263     yoffset = 0;
264     even = false;
265     weight = 1;
266    
267     if (hwaccum)
268     glClear(GL_ACCUM_BUFFER_BIT);
269     else
270     {
271     free (pixbuf); pixbuf = 0;
272     free (accumbuf); accumbuf = 0;
273     accsum = 0;
274     }
275     }
276    
277     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
278    
279     glMatrixMode(GL_MODELVIEW);
280     glPushMatrix ();
281    
282     glRotated ( deltax, 0, 1, 0);
283     glRotated (-deltay, 1, 0, 1);
284    
285     double sc;
286    
287     sc = abs(4/(x2-x1));
288     if (abs (4/(y2-y1)) < sc) sc = abs(4/(y2-y1));
289     if (abs (4/(z2-z1)) < sc) sc = abs(4/(z2-z1));
290     glScaled (sc, sc, -sc);
291    
292     glTranslated (-0.5*(x2+x1),-0.5*(y2+y1), -0.5*(z1+z2));
293    
294     glMatrixMode(GL_PROJECTION);
295     glPushMatrix ();
296     glTranslated (xoffset*10/vW, yoffset*10/vH, 0);
297    
298     glCallList (TREE_LIST);
299    
300     glPopMatrix ();
301     glMatrixMode(GL_MODELVIEW);
302     glPopMatrix ();
303    
304     if (buttondown || !antialias)
305     {
306     glXSwapBuffers (dpy, win);
307     continue;
308     }
309    
310     if (hwaccum)
311     glAccum (GL_ACCUM, weight);
312     else
313     {
314     if (!pixbuf ) pixbuf = (pix_t *) malloc (wWHD * sizeof (pix_t));
315     if (!accumbuf) accumbuf = (acc_t *) calloc (wWHD , sizeof (acc_t));
316    
317     glReadPixels (0, 0, wW, wH, fb_format, GL_UNSIGNED_BYTE, pixbuf);
318    
319     acc_t scale[256]; // 256 == pix_t range
320     for (int t = 0; t < 256; t++)
321     scale[t] = acc_t (float (t) * acc_scale * weight);
322    
323     pix_t *p;
324     acc_t *a;
325     for (p = pixbuf, a = accumbuf;
326     p < pixbuf + wWHD;
327     p++, a++)
328     *a += scale[*p];
329     }
330    
331     cout << setw(9) << stepsize << " "
332     << setw(9) << 1 - yoffset << "\r" << flush;
333    
334     xoffset += even ? stepsize*0.5 : stepsize;
335     if (xoffset >= 1.0)
336     {
337     yoffset += stepsize*0.5;
338     if (yoffset >= 1.0)
339     {
340     if (hwaccum)
341     {
342     glAccum (GL_RETURN, 1.);
343     glXSwapBuffers (dpy, win);
344     glAccum (GL_MULT, 0.25);
345     }
346     else
347     {
348     pix_t *p;
349     acc_t *a;
350     for (p = pixbuf, a = accumbuf;
351     p < pixbuf + wWHD;
352     p++, a++)
353     {
354     *p = *a / acc_scale;
355     *a /= 4;
356     }
357    
358     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
359    
360     glMatrixMode (GL_MODELVIEW);
361     glPushMatrix ();
362     glLoadIdentity ();
363     glMatrixMode (GL_PROJECTION);
364     glPushMatrix ();
365     glLoadIdentity ();
366    
367     glRasterPos2f (float(-vX) / float(vW / 2) - 1, float(-vY) / float(vH / 2) - 1);
368     glDrawPixels (wW, wH, fb_format, GL_UNSIGNED_BYTE, pixbuf);
369     glPopMatrix ();
370    
371     glMatrixMode (GL_MODELVIEW);
372     glPopMatrix ();
373    
374     glXSwapBuffers (dpy, win);
375    
376     accsum /= 4;
377     }
378    
379     yoffset = 0;
380     even = true;
381     stepsize *= 0.5;
382     weight *= 0.25;
383     antialias = false;
384     }
385    
386     even = !even;
387     xoffset = even ? 0 : stepsize*0.5;
388     }
389    
390     }
391    
392     free (pixbuf);
393     free (accumbuf);
394    
395     glDeleteLists (TREE_LIST, 1);
396     }
397    
398     void gl_int::clip (const vec &v) t_no
399     {
400     if (x1 > v[0]) x1 = v[0];
401     if (y1 > v[1]) y1 = v[1];
402     if (z1 > v[2]) z1 = v[2];
403    
404     if (x2 < v[0]) x2 = v[0];
405     if (y2 < v[1]) y2 = v[1];
406     if (z2 < v[2]) z2 = v[2];
407     }
408    
409     void gl_int::check_attrs (const attribute_set &attr) t_err
410     {
411     vec v;
412    
413     if (!in_begin)
414     glLineWidth (attr ("width",1));
415    
416     v = attr("color", vec( 1, 1, 1));
417     float col[4];
418     col[0] = v[0];
419     col[1] = v[1];
420     col[2] = v[2];
421     col[3] = 1.0;
422     glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
423     }
424    
425     void gl_int::segment (const point &a, const point &b) t_err
426     {
427     check_attrs (a.attr);
428    
429     Begin (GL_LINES);
430     glNormal (vec (0, 0, 0));
431     glVertex (a.v); clip(a.v);
432     glVertex (b.v); clip(b.v);
433     End ();
434     }
435    
436     void gl_int::object (const points &v) t_err
437     {
438     // cerr << "polygon "; for (points::const_iterator j = v.begin (); j != v.end (); j++) cerr << j->first << " "; cerr << endl;
439     if (v.size () < 3)
440     return;
441    
442     glFrontFace (winding (v) > 0 ? GL_CCW : GL_CW);
443    
444     check_attrs (v.front ().attr);
445    
446     Begin (GL_POLYGON);
447     for(points::const_iterator i = v.begin (); i != v.end(); ++i)
448     {
449     check_attrs (i->attr);
450     glNormal (i->n);
451     glVertex (i->v);
452     clip (i->v);
453     }
454     End ();
455    
456     double len;
457    
458     if ((len = v.front ().attr ("draw_normals", 0)))
459     {
460     glNormal (vec (0, 0, 0));
461    
462     Begin (GL_LINES);
463     for(points::const_iterator i = v.begin (); i != v.end(); ++i)
464     {
465     glVertex (i->v);
466     glVertex (i->v + len * i->n);
467     }
468     End ();
469     }
470     }
471    
472     #endif
473