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, 5 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Log Message:
*** empty log message ***

File Contents

# Content
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