2 * engine.c - GL representation of a 4 stroke engine
6 * Copyright (C) 2001 Ben Buxton (bb@cactii.net)
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that
11 * copyright notice and this permission notice appear in supporting
12 * documentation. No representations are made about the suitability of this
13 * software for any purpose. It is provided "as is" without express or
18 #include <X11/Intrinsic.h>
21 # define PROGCLASS "Engine"
22 # define HACK_INIT init_engine
23 # define HACK_DRAW draw_engine
24 # define HACK_HANDLE_EVENT engine_handle_event
25 # define HACK_RESHAPE reshape_engine
26 # define EVENT_MASK PointerMotionMask
27 # define engine_opts xlockmore_opts
28 /* insert defaults here */
30 #define DEFAULTS "*delay: 10000 \n" \
31 "*showFPS: False \n" \
36 # include "xlockmore.h" /* from the xscreensaver distribution */
37 #else /* !STANDALONE */
38 # include "xlock.h" /* from the xlockmore distribution */
39 #endif /* !STANDALONE */
42 #include "gltrackball.h"
44 /* lifted from lament.c */
45 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
46 #define RANDSIGN() ((random() & 1) ? 1 : -1)
54 static int rotatespeed;
56 static int movepaused = 0;
60 #define countof(x) (sizeof((x))/sizeof((*x)))
62 static XrmOptionDescRec opts[] = {
63 {"-rotate-speed", ".engine.rotatespeed", XrmoptionSepArg, "1" },
64 {"-move", ".engine.move", XrmoptionNoArg, (caddr_t) "true" },
65 {"+move", ".engine.move", XrmoptionNoArg, (caddr_t) "false" },
66 {"-spin", ".engine.spin", XrmoptionNoArg, (caddr_t) "true" },
67 {"+spin", ".engine.spin", XrmoptionNoArg, (caddr_t) "false" },
70 static argtype vars[] = {
71 {(caddr_t *) &rotatespeed, "rotatespeed", "Rotatespeed", "1", t_Int},
72 {(caddr_t *) &move, "move", "Move", "True", t_Bool},
73 {(caddr_t *) &spin, "spin", "Spin", "True", t_Bool},
76 ModeSpecOpt engine_opts = {countof(opts), opts, countof(vars), vars, NULL};
79 ModStruct engine_description =
80 {"engine", "init_engine", "draw_engine", "release_engine",
81 "draw_engine", "init_engine", NULL, &engine_opts,
82 1000, 1, 2, 1, 4, 1.0, "",
83 "A four stroke engine", 0, NULL};
89 GLXContext *glx_context;
91 GLfloat x, y, z; /* position */
92 GLfloat dx, dy, dz; /* position */
93 GLfloat an1, an2, an3; /* internal angle */
94 GLfloat nx, ny, nz; /* spin vector */
95 GLfloat a; /* spin angle */
96 GLfloat da; /* spin speed */
98 trackball_state *trackball;
102 static Engine *engine = NULL;
105 #include <sys/time.h>
110 #define M_PI 3.14159265
113 #define MOVE_MULT 0.05
115 #define RAND_RANGE(min, max) ((min) + (max - min) * f_rand())
119 static GLfloat viewer[] = {0.0, 0.0, 30.0};
120 static GLfloat lookat[] = {0.0, 0.0, 0.0};
121 static GLfloat lightpos[] = {7.0, 7.0, 12, 1.0};
122 GLfloat light_sp[] = {0.8, 0.8, 0.8, 0.5};
123 static GLfloat red[] = {1.0, 0, 0, 1.0};
124 static GLfloat green[] = {0.0, 1, 0, 1.0};
125 static GLfloat blue[] = {0, 0, 1, 1.0};
126 static GLfloat white[] = {1.0, 1, 1, 1.0};
127 static GLfloat yellow_t[] = {1, 1, 0, 0.4};
129 void circle(float, int,int);
130 GLvoid normal(GLfloat [], GLfloat [], GLfloat [],
131 GLfloat *, GLfloat *, GLfloat *);
133 float sin_table[720];
134 float cos_table[720];
135 float tan_table[720];
137 /* we use trig tables to speed things up - 200 calls to sin()
138 in one frame can be a bit harsh..
141 void make_tables(void) {
145 f = 360 / (M_PI * 2);
146 for (i = 0 ; i <= 720 ; i++) {
147 sin_table[i] = sin(i/f);
149 for (i = 0 ; i <= 720 ; i++) {
150 cos_table[i] = cos(i/f);
152 for (i = 0 ; i <= 720 ; i++) {
153 tan_table[i] = tan(i/f);
157 /* if inner and outer are the same, we draw a cylinder, not a tube */
158 /* for a tube, endcaps is 0 (none), 1 (left), 2 (right) or 3(both) */
159 /* angle is how far around the axis to go (up to 360) */
161 void cylinder (GLfloat x, GLfloat y, GLfloat z, float length, float outer, float inner, int endcaps, int sang,
163 int a; /* current angle around cylinder */
164 int b = 0; /* previous */
165 int angle, norm, step, sangle;
166 float z1, y1, z2, y2, ex=0;
168 float Z1, Y1, Z2, Y2, xl, Y3, Z3;
169 GLfloat y2c[720], z2c[720];
170 GLfloat ony, onz; /* previous normals */
174 nsegs = outer*(MAX(win_w, win_h)/200);
175 nsegs = MAX(nsegs, 6);
176 nsegs = MAX(nsegs, 40);
182 z1 = cos_table[sangle]*outer+z; y1 = sin_table[sangle] * outer+y;
183 Z1 = cos_table[sangle] * inner+z; Y1 = sin_table[sangle]*inner+y ;
187 if (inner < outer && endcaps < 3) tube = 1;
191 for (a = sangle ; a <= angle || b <= angle ; a+= step) {
192 y2=outer*(float)sin_table[a]+y;
193 z2=outer*(float)cos_table[a]+z;
194 y3=outer*(float)sin_table[a+step]+y;
195 z3=outer*(float)cos_table[a+step]+z;
197 y2c[a] = y2; z2c[a] = z2; /* cache for later */
199 Y2=inner*(float)sin_table[a]+y;
200 Z2=inner*(float)cos_table[a]+z;
201 Y3=inner*(float)sin_table[a+step]+y;
202 Z3=inner*(float)cos_table[a+step]+z;
204 glNormal3f(0, y1, z1);
206 glVertex3f(xl,y1,z1);
207 glNormal3f(0, y2, z2);
208 glVertex3f(xl,y2,z2);
210 if (a == sangle && angle - sangle < 360) {
212 glVertex3f(x, Y1, Z1);
215 glVertex3f(x, y1, z1);
216 glVertex3f(xl, y1, z1);
218 glVertex3f(xl, Z1, Z1);
220 glVertex3f(xl, y, z);
224 glNormal3f(-1, 0, 0); /* left end */
225 glVertex3f(x, y1, z1);
226 glVertex3f(x, y2, z2);
227 glVertex3f(x, Y2, Z2);
228 glVertex3f(x, Y1, Z1);
231 glNormal3f(0, -Y1, -Z1); /* inner surface */
232 glVertex3f(x, Y1, Z1);
233 glVertex3f(xl, Y1, Z1);
234 glNormal3f(0, -Y2, -Z2);
235 glVertex3f(xl, Y2, Z2);
236 glVertex3f(x, Y2, Z2);
239 glNormal3f(1, 0, 0); /* right end */
240 glVertex3f(xl, y1, z1);
241 glVertex3f(xl, y2, z2);
242 glVertex3f(xl, Y2, Z2);
243 glVertex3f(xl, Y1, Z1);
253 if (angle - sangle < 360) {
255 GLfloat v1[3], v2[3], v3[3];
256 v1[0] = x; v1[1] = y; v1[2] = z;
257 v2[0] = x; v2[1] = y1; v2[2] = z1;
258 v3[0] = xl; v3[1] = y1; v3[2] = z1;
259 normal(&v2[0], &v1[0], &v3[0], &nx, &ny, &nz);
261 glNormal3f(nx, ny, nz);
263 glVertex3f(x, y1, z1);
264 glVertex3f(xl, y1, z1);
265 glVertex3f(xl, y, z);
274 } else if (endcaps == 2) {
275 start = end = length+0.01;
277 end = length+0.02; start = -0.01;
279 norm = (ex == length+0.01) ? -1 : 1;
286 for(ex = start ; ex <= end ; ex += length) {
287 z1 = outer*cos_table[sangle]+z;
288 y1 = y+sin_table[sangle]*outer;
290 glBegin(GL_TRIANGLES);
292 for (a = sangle ; a <= angle || b <= angle; a+= step) {
293 glNormal3f(norm, 0, 0);
294 glVertex3f(x+ex,y, z);
295 glVertex3f(x+ex,y1,z1);
296 glVertex3f(x+ex,y2c[a],z2c[a]);
297 y1 = y2c[a]; z1 = z2c[a];
307 GLvoid normal(GLfloat v1[], GLfloat v2[], GLfloat v3[],
308 GLfloat *nx, GLfloat *ny, GLfloat *nz)
310 GLfloat x, y, z, X, Y, Z;
327 void circle(float radius, int segments, int half) {
328 float x1 = 0, x2 = 0;
329 float y1 = 0, y2 = 0;
338 glBegin(GL_TRIANGLES);
343 x2=radius*(float)cos_table[(int)angle];
344 y2=radius*(float)sin_table[(int)angle];
354 void ring(GLfloat inner, GLfloat outer, int nsegs) {
355 GLfloat z1, z2, y1, y2;
356 GLfloat Z1, Z2, Y1, Y2;
363 for(i=0; i <=360 ; i+= 360/nsegs)
366 z2=inner*(float)sin_table[(int)angle];
367 y2=inner*(float)cos_table[(int)angle];
368 Z2=outer*(float)sin_table[(int)angle];
369 Y2=outer*(float)cos_table[(int)angle];
370 glVertex3f(0, Y1, Z1);
371 glVertex3f(0, y1, z1);
372 glVertex3f(0, y2, z2);
373 glVertex3f(0, Y2, Z2);
382 void Rect(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h,
388 yh = y+h; xw = x+w; zt = z - t;
390 glBegin(GL_QUADS); /* front */
393 glVertex3f(x, yh, z);
394 glVertex3f(xw, yh, z);
395 glVertex3f(xw, y, z);
397 glNormal3f(0, 0, -1);
398 glVertex3f(x, y, zt);
399 glVertex3f(x, yh, zt);
400 glVertex3f(xw, yh, zt);
401 glVertex3f(xw, y, zt);
404 glVertex3f(x, yh, z);
405 glVertex3f(x, yh, zt);
406 glVertex3f(xw, yh, zt);
407 glVertex3f(xw, yh, z);
409 glNormal3f(0, -1, 0);
411 glVertex3f(x, y, zt);
412 glVertex3f(xw, y, zt);
413 glVertex3f(xw, y, z);
415 glNormal3f(-1, 0, 0);
417 glVertex3f(x, y, zt);
418 glVertex3f(x, yh, zt);
419 glVertex3f(x, yh, z);
422 glVertex3f(xw, y, z);
423 glVertex3f(xw, y, zt);
424 glVertex3f(xw, yh, zt);
425 glVertex3f(xw, yh, z);
429 void makepiston(void) {
430 GLfloat colour[] = {0.6, 0.6, 0.6, 1.0};
434 glNewList(i, GL_COMPILE);
435 glRotatef(90, 0, 0, 1);
436 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colour);
437 glMaterialfv(GL_FRONT, GL_SPECULAR, colour);
438 glMateriali(GL_FRONT, GL_SHININESS, 20);
439 cylinder(0, 0, 0, 2, 1, 0.7, 2, 0, 360); /* body */
440 colour[0] = colour[1] = colour[2] = 0.2;
441 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colour);
442 cylinder(1.6, 0, 0, 0.1, 1.05, 1.05, 0, 0, 360); /* ring */
443 cylinder(1.8, 0, 0, 0.1, 1.05, 1.05, 0, 0, 360); /* ring */
447 void CrankBit(GLfloat x, GLfloat y, GLfloat z) {
448 Rect(x, y, z, 0.2, 1.8, 1);
451 void boom(GLfloat x, GLfloat y, int s) {
452 static GLfloat red[] = {0, 0, 0, 0.9};
453 static GLfloat lpos[] = {0, 0, 0, 1};
454 static GLfloat d = 0, wd;
457 if (time == 0 && s) {
462 } else if (time == 0 && !s) {
464 } else if (time >= 8 && time < 16 && !s) {
466 red[0] -= 0.2; red[1] -= 0.1;
468 } else if (time >= 16) {
470 glDisable(GL_LIGHT1);
473 red[0] += 0.2; red[1] += 0.1;
477 lpos[0] = x; lpos[1] = y-d;
478 glLightfv(GL_LIGHT1, GL_POSITION, lpos);
479 glLightfv(GL_LIGHT1, GL_DIFFUSE, red);
480 glLightfv(GL_LIGHT1, GL_SPECULAR, red);
481 glLighti(GL_LIGHT1, GL_LINEAR_ATTENUATION, 1.3);
482 glLighti(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 0);
484 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
486 glRotatef(90, 0, 0, 1);
488 if (wd > 0.7) wd = 0.7;
490 glDepthMask(GL_FALSE);
491 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
492 cylinder(y-d, -x, 0, d, wd, wd, 1, 0, 360);
493 glDepthMask(GL_TRUE);
498 void display(Engine *e) {
502 static GLfloat ln[730], yp[730], ang[730];
503 static int ln_init = 0;
506 glEnable(GL_LIGHTING);
507 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
509 gluLookAt(viewer[0], viewer[1], viewer[2], lookat[0], lookat[1], lookat[2], 0.0, 1.0, 0.0);
511 glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
512 glLightfv(GL_LIGHT0, GL_SPECULAR, light_sp);
513 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_sp);
517 get_position (e->rot, &x, &y, &z, !e->button_down_p);
518 glTranslatef(x*16-9, y*14-7, z*16-10);
522 gltrackball_rotate (e->trackball);
523 get_rotation(e->rot, &x, &y, &z, !e->button_down_p);
524 glRotatef(x*360, 1.0, 0.0, 0.0);
525 glRotatef(y*360, 0.0, 1.0, 0.0);
526 glRotatef(x*360, 0.0, 0.0, 1.0);
529 /* So the rotation appears around the centre of the engine */
530 glTranslatef(-5, 0, 0);
534 glRotatef(a, 1, 0, 0);
538 /* init the ln[] matrix for speed */
540 for (ln_init = 0 ; ln_init < 730 ; ln_init++) {
541 zb = sin_table[ln_init];
542 yb = cos_table[ln_init];
543 yp[ln_init] = yb + sqrt(25 - (zb*zb)); /* y ordinate of piston */
544 ln[ln_init] = sqrt(zb*zb + (yb-yp[ln_init])*(yb-yp[ln_init])); /* length of rod */
545 ang[ln_init] = asin(zb/5)*57; /* angle of connecting rod */
554 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white);
556 glTranslatef(0, yp[a]-0.3, 0);
560 glTranslatef(3.2, yp[(a > 180 ? a-180 : a+180)]-0.3, 0);
564 glTranslatef(6.5, yp[a]-0.3, 0);
568 glTranslatef(9.8, yp[(a > 180 ? a-180 : a+180)]-0.3, 0);
574 glRotatef(90, 0, 0, 1);
575 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
576 cylinder(8.5, 0, 0, 0.5, 0.4, 0.3, 1, 0, 360);
577 cylinder(8.5, -3.2, 0, 0.5, 0.4, 0.3, 1, 0, 360);
578 cylinder(8.5, -6.5, 0, 0.5, 0.4, 0.3, 1, 0, 360);
579 cylinder(8.5, -9.8, 0, 0.5, 0.4, 0.3, 1, 0, 360);
581 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white);
582 cylinder(8, 0, 0, 0.5, 0.2, 0.2, 1, 0, 360);
583 cylinder(8, -3.2, 0, 0.5, 0.2, 0.2, 1, 0, 360);
584 cylinder(8, -6.5, 0, 0.5, 0.2, 0.2, 1, 0, 360);
585 cylinder(8, -9.8, 0, 0.5, 0.2, 0.2, 1, 0, 360);
587 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white);
588 cylinder(9, 0, 0, 1, 0.15, 0.15, 1, 0, 360);
589 cylinder(9, -3.2, 0, 1, 0.15, 0.15, 1, 0, 360);
590 cylinder(9, -6.5, 0, 1, 0.15, 0.15, 1, 0, 360);
591 cylinder(9, -9.8, 0, 1, 0.15, 0.15, 1, 0, 360);
595 if (a == 0) spark = 1 - spark;
619 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
621 cylinder(-0.8, yb, zb, 1.6, 0.3, 0.3, 1, 0, 365);
622 cylinder(5.7, yb, zb, 1.7, 0.3, 0.3, 1, 0, 365);
624 cylinder(2.4, -yb, -zb, 1.7, 0.3, 0.3, 1, 0, 365);
625 cylinder(9.0, -yb, -zb, 1.7, 0.3, 0.3, 1, 0, 365);
630 glRotatef(90, 0, 0, 1);
631 glRotatef(ang[a], 0, -1, 0);
632 cylinder(yb, 0, zb, ln[a], 0.2, 0.2, 0, 0, 365);
633 cylinder(yb, -6.4, zb, ln[a], 0.2, 0.2, 0, 0, 365);
637 glRotatef(90, 0, 0, 1);
638 glRotatef(ang[a+180], 0, -1, 0);
639 cylinder(-yb, -3.2, -zb, ln[a], 0.2, 0.2, 0, 0, 365);
640 cylinder(-yb, -9.7, -zb, ln[a], 0.2, 0.2, 0, 0, 365);
644 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, yellow_t);
646 glDepthMask(GL_FALSE);
647 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
649 Rect(-1, 8.3, 1, 12, 0.2, 2);
650 Rect(-1.2, -0.5, 1, 0.2, 9, 2);
652 Rect(1.4, 3, 1, 0.6, 5.3, 2);
653 Rect(4.4, 3, 1, 1, 5.3, 2);
654 Rect(7.7, 3, 1, 0.8, 5.3, 2);
655 Rect(10.8, -0.5, 1, 0.2, 8.8, 2);
657 Rect(-1, 2.8, 1, 12, 0.2, 0.2);
658 Rect(-1, 2.8, -1, 12, 0.2, 0.2);
660 glDepthMask(GL_TRUE);
664 a+=10; if (a >= 360) a = 0;
669 void makeshaft (void) {
672 glNewList(i, GL_COMPILE);
673 cylinder(10.4, 0, 0, 2, 0.3, 0.3, 1, 0, 365);
674 cylinder(7.1, 0, 0, 2, 0.3, 0.3, 0, 0, 365);
675 cylinder(3.8, 0, 0, 2, 0.3, 0.3, 0, 0, 365);
676 cylinder(0.5, 0, 0, 2, 0.3, 0.3, 0, 0, 365);
677 cylinder(-1.5, 0, 0, 1, 0.3, 0.3, 1, 0, 365);
679 cylinder(12.4, 0, 0, 1, 3, 2.5, 0, 0, 365);
680 Rect(12.4, -0.3, 2.8, 0.5, 0.6, 5.6);
681 Rect(12.4, -2.8, 0.3, 0.5, 5.6, 0.6);
683 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
684 CrankBit(0.5, -0.4, 0.5);
685 cylinder(0.5, 0.5, 0, 0.2, 2, 2, 1, 240, 300);
686 CrankBit(-0.7, -0.4, 0.5);
687 cylinder(-0.7, 0.5, 0, 0.2, 2, 2, 1, 240, 300);
689 CrankBit(2.5, -1.4, 0.5);
690 cylinder(2.5, -0.5, 0, 0.2, 2, 2, 1, 60, 120);
691 CrankBit(3.8, -1.4, 0.5);
692 cylinder(3.8, -0.5, 0, 0.2, 2, 2, 1, 60, 120);
694 CrankBit(5.8, -0.4, 0.5);
695 cylinder(5.8, 0.5, 0, 0.2, 2, 2, 1, 240, 300);
696 CrankBit(7.1, -0.4, 0.5);
697 cylinder(7.1, 0.5, 0, 0.2, 2, 2, 1, 240, 300);
699 CrankBit(9.1, -1.4, 0.5);
700 cylinder(9.1, -0.5, 0, 0.2, 2, 2, 1, 60, 120);
701 CrankBit(10.4, -1.4, 0.5);
702 cylinder(10.4, -0.5, 0, 0.2, 2, 2, 1, 60, 120);
708 void reshape_engine(ModeInfo *mi, int width, int height)
711 glViewport(0,0,(GLint)width, (GLint) height);
712 glMatrixMode(GL_PROJECTION);
714 glFrustum(-1.0,1.0,-1.0,1.0,1.5,70.0);
715 glMatrixMode(GL_MODELVIEW);
716 win_h = height; win_w = width;
720 void init_engine(ModeInfo *mi)
722 int screen = MI_SCREEN(mi);
725 if (engine == NULL) {
726 if ((engine = (Engine *) calloc(MI_NUM_SCREENS(mi),
727 sizeof(Engine))) == NULL)
731 e->window = MI_WINDOW(mi);
733 e->x = e->y = e->z = e->a = e->an1 = e->nx = e->ny = e->nz =
734 e->dx = e->dy = e->dz = e->da = 0;
737 e->dx = (float)(random() % 1000)/30000;
738 e->dy = (float)(random() % 1000)/30000;
739 e->dz = (float)(random() % 1000)/30000;
741 viewer[0] = 0; viewer[1] = 6; viewer[2] = 15;
742 lookat[0] = 0; lookat[1] = 4; lookat[2] = 0;
745 e->da = (float)(random() % 1000)/125 - 4;
746 e->nx = (float)(random() % 100) / 100;
747 e->ny = (float)(random() % 100) / 100;
748 e->nz = (float)(random() % 100) / 100;
752 double spin_speed = 1.0;
753 double wander_speed = 0.03;
755 e->rot = make_rotator (spin ? spin_speed : 0,
756 spin ? spin_speed : 0,
757 spin ? spin_speed : 0,
759 move ? wander_speed : 0,
762 e->trackball = gltrackball_init ();
765 if ((e->glx_context = init_GL(mi)) != NULL) {
766 reshape_engine(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
770 glClearColor(0.0,0.0,0.0,0.0);
771 glShadeModel(GL_SMOOTH);
772 glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
773 glEnable(GL_DEPTH_TEST);
774 glEnable(GL_LIGHTING);
776 glEnable(GL_NORMALIZE);
782 Bool engine_handle_event (ModeInfo *mi, XEvent *event) {
783 Engine *e = &engine[MI_SCREEN(mi)];
785 if (event->xany.type == ButtonPress &&
786 event->xbutton.button & Button1)
788 e->button_down_p = True;
789 gltrackball_start (e->trackball,
790 event->xbutton.x, event->xbutton.y,
791 MI_WIDTH (mi), MI_HEIGHT (mi));
795 else if (event->xany.type == ButtonRelease &&
796 event->xbutton.button & Button1) {
797 e->button_down_p = False;
801 else if (event->xany.type == MotionNotify &&
803 gltrackball_track (e->trackball,
804 event->xmotion.x, event->xmotion.y,
805 MI_WIDTH (mi), MI_HEIGHT (mi));
811 void draw_engine(ModeInfo *mi) {
812 Engine *e = &engine[MI_SCREEN(mi)];
813 Window w = MI_WINDOW(mi);
814 Display *disp = MI_DISPLAY(mi);
819 glXMakeCurrent(disp, w, *(e->glx_context));
824 if(mi->fps_p) do_fps(mi);
826 glXSwapBuffers(disp, w);
829 void release_engine(ModeInfo *mi) {
831 if (engine != NULL) {
832 (void) free((void *) engine);