2 * Permission to use, copy, modify, and distribute this software and its
3 * documentation for any purpose and without fee is hereby granted,
4 * provided that the above copyright notice appear in all copies and that
5 * both that copyright notice and this permission notice appear in
6 * supporting documentation.
8 * This file is provided AS IS with no warranties of any kind. The author
9 * shall have no liability with respect to the infringement of copyrights,
10 * trade secrets or any patents by this file or any part thereof. In no
11 * event will the author be liable for any lost revenue or profits or
12 * other special, indirect and consequential damages.
14 * Copyright 2004 Blair Tennessy
18 #include <X11/Intrinsic.h>
21 #define PROGCLASS "AntInspect"
22 #define HACK_INIT init_antinspect
23 #define HACK_DRAW draw_antinspect
24 #define HACK_RESHAPE reshape_antinspect
25 #define HACK_HANDLE_EVENT antinspect_handle_event
26 #define EVENT_MASK PointerMotionMask
27 #define antinspect_opts xlockmore_opts
28 #define DEFAULTS "*delay: 20000 \n" \
31 #include "xlockmore.h"
37 #include "gltrackball.h"
39 #define DEF_SHADOWS "True"
43 static XrmOptionDescRec opts[] = {
44 {"-shadows", ".antinspect.shadows", XrmoptionNoArg, "on"},
45 {"+shadows", ".antinspect.shadows", XrmoptionNoArg, "off"}
48 static argtype vars[] = {
49 {&shadows, "shadows", "Shadows", DEF_SHADOWS, t_Bool}
52 static OptionStruct desc[] = {
53 {"-/+shadows", "turn on/off ant shadows"}
56 ModeSpecOpt antinspect_opts = {sizeof opts / sizeof opts[0],
58 sizeof vars / sizeof vars[0],
63 ModStruct antinspect_description =
64 {"antinspect", "init_antinspect", "draw_antinspect", "release_antinspect",
65 "draw_antinspect", "change_antinspect", (char *) NULL, &antinspect_opts,
66 1000, 1, 1, 1, 4, 1.0, "",
67 "draws some ants", 0, NULL};
70 #define Scale4Window 0.3
71 #define Scale4Iconic 0.4
73 #define sqr(A) ((A)*(A))
79 #define ObjAntinspectStrip 0
83 /*************************************************************************/
89 GLXContext *glx_context;
90 trackball_state *trackball;
94 static float front_shininess[] = {60.0};
95 static float front_specular[] = {0.7, 0.7, 0.7, 1.0};
96 static float ambient[] = {0.0, 0.0, 0.0, 1.0};
97 static float diffuse[] = {1.0, 1.0, 1.0, 1.0};
98 static float position0[] = {0.0, 3.0, 0.0, 1.0};
99 static float position1[] = {-1.0, -3.0, 1.0, 0.0};
100 static float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
101 static float lmodel_twoside[] = {GL_TRUE};
103 static float MaterialRed[] = {0.6, 0.0, 0.0, 1.0};
104 static float MaterialOrange[] = {1.0, 0.69, 0.00, 1.0};
105 static float MaterialGray[] = {0.2, 0.2, 0.2, 1.0};
106 static float MaterialBlack[] = {0.1, 0.1, 0.1, 0.4};
107 static float MaterialShadow[] = {0.3, 0.3, 0.3, 0.3};
108 static float MaterialGray5[] = {0.5, 0.5, 0.5, 0.3};
109 static float MaterialGray6[] = {0.6, 0.6, 0.6, 1.0};
111 static antinspectstruct *antinspect = (antinspectstruct *) NULL;
118 /* create a matrix that will project the desired shadow */
119 void shadowmatrix(GLfloat shadowMat[4][4],
120 GLfloat groundplane[4],
121 GLfloat lightpos[4]) {
124 /* find dot product between light position vector and ground plane normal */
125 dot = groundplane[X] * lightpos[X] +
126 groundplane[Y] * lightpos[Y] +
127 groundplane[Z] * lightpos[Z] +
128 groundplane[W] * lightpos[W];
130 shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
131 shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
132 shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
133 shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
135 shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
136 shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
137 shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
138 shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
140 shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
141 shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
142 shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
143 shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
145 shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
146 shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
147 shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
148 shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
151 GLfloat ground[4] = {0.0, 1.0, 0.0, -0.00001};
153 /* simple filled sphere */
154 static Bool mySphere(float radius) {
155 GLUquadricObj *quadObj;
157 if((quadObj = gluNewQuadric()) == 0)
159 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
160 gluSphere(quadObj, radius, 16, 16);
161 gluDeleteQuadric(quadObj);
167 static Bool mySphere2(float radius) {
168 GLUquadricObj *quadObj;
170 if((quadObj = gluNewQuadric()) == 0)
172 gluQuadricDrawStyle(quadObj, (GLenum) GLU_LINE);/*GLU_SILHOUETTE);*/
173 gluSphere(quadObj, radius, 16, 8);
174 gluDeleteQuadric(quadObj);
180 static Bool myCone2(float radius) {
185 static float ant_step = 0;
188 static Bool draw_antinspect_ant(antinspectstruct * mp, float *Material, int mono,
189 Bool (*sphere)(float), Bool (*cone)(float)) {
190 float cos1 = cos(ant_step);
191 float cos2 = cos(ant_step + 2 * Pi / 3);
192 float cos3 = cos(ant_step + 4 * Pi / 3);
193 float sin1 = sin(ant_step);
194 float sin2 = sin(ant_step + 2 * Pi / 3);
195 float sin3 = sin(ant_step + 4 * Pi / 3);
198 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
200 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Material);
201 glEnable(GL_CULL_FACE);
204 if (!((*sphere)(0.18)))
206 glScalef(1, 1 / 1.3, 1);
207 glTranslatef(0.00, 0.30, 0.00);
208 if (!((*sphere)(0.2)))
211 glTranslatef(-0.05, 0.17, 0.05);
212 glRotatef(-90, 1, 0, 0);
213 glRotatef(-25, 0, 1, 0);
214 if (!((*cone)(0.05)))
216 glTranslatef(0.00, 0.10, 0.00);
217 if (!((*cone)(0.05)))
219 glRotatef(25, 0, 1, 0);
220 glRotatef(90, 1, 0, 0);
223 glTranslatef(0.15, -0.65, 0.05);
224 if (!((*sphere)(0.25)))
226 glScalef(1, 1 / 1.3, 1);
228 glDisable(GL_CULL_FACE);
230 glDisable(GL_LIGHTING);
235 glColor3fv(MaterialGray5);
237 glColor3fv(Material);
238 glVertex3f(0.00, 0.30, 0.00);
239 glColor3fv(MaterialGray);
240 glVertex3f(0.40, 0.70, 0.40);
242 glColor3fv(MaterialGray5);
244 glColor3fv(Material);
245 glVertex3f(0.00, 0.30, 0.00);
246 glColor3fv(MaterialGray);
247 glVertex3f(0.40, 0.70, -0.40);
251 glColor3fv(MaterialGray6);
253 glColor3fv(Material);
254 glVertex3f(0.40, 0.70, 0.40);
255 glVertex3f(0.40, 0.70, -0.40);
259 glBegin(GL_LINE_STRIP);
261 glColor3fv(MaterialGray5);
263 glColor3fv(Material);
264 glVertex3f(0.00, 0.05, 0.18);
265 glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25);
266 glColor3fv(MaterialGray);
267 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
270 /* LEFT-CENTER ARM */
271 glBegin(GL_LINE_STRIP);
273 glColor3fv(MaterialGray5);
275 glColor3fv(Material);
276 glVertex3f(0.00, 0.00, 0.18);
277 glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25);
278 glColor3fv(MaterialGray);
279 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
283 glBegin(GL_LINE_STRIP);
285 glColor3fv(MaterialGray5);
287 glColor3fv(Material);
288 glVertex3f(0.00, -0.05, 0.18);
289 glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25);
290 glColor3fv(MaterialGray);
291 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
294 /* RIGHT-FRONT ARM */
295 glBegin(GL_LINE_STRIP);
297 glColor3fv(MaterialGray5);
299 glColor3fv(Material);
300 glVertex3f(0.00, 0.05, -0.18);
301 glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25);
302 glColor3fv(MaterialGray);
303 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
306 /* RIGHT-CENTER ARM */
307 glBegin(GL_LINE_STRIP);
309 glColor3fv(MaterialGray5);
311 glColor3fv(Material);
312 glVertex3f(0.00, 0.00, -0.18);
313 glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25);
314 glColor3fv(MaterialGray);
315 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
319 glBegin(GL_LINE_STRIP);
321 glColor3fv(MaterialGray5);
323 glColor3fv(Material);
324 glVertex3f(0.00, -0.05, -0.18);
325 glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25);
326 glColor3fv(MaterialGray);
327 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
330 glEnable(GL_LIGHTING);
335 /* only works with 3 right now */
338 float MaterialBen[4] = {0.25, 0.30, 0.46, 1.0};
340 static float* antmaterial[ANTCOUNT] =
341 {MaterialRed, MaterialBen, MaterialOrange};
342 static double antposition[ANTCOUNT] = {0.0, 120.0, 240.0};
343 static double antvelocity[ANTCOUNT] = {0.3, 0.3, 0.3};
344 static double antsphere[ANTCOUNT] = {1.2, 1.2, 1.2};
347 static double antorder[6][ANTCOUNT] = {{0, 1, 2},
355 static Bool draw_antinspect_strip(ModeInfo * mi) {
356 antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
358 int mono = MI_IS_MONO(mi);
360 int ro = (((int)antposition[1])/(360/(2*ANTCOUNT))) % (2*ANTCOUNT);
362 glEnable(GL_TEXTURE_2D);
364 glLightfv(GL_LIGHT0, GL_POSITION, position0);
366 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
367 glRotatef(-30.0, 0.0, 1.0, 0.0);
369 glDisable(GL_TEXTURE_2D);
372 /* render ground plane */
373 glBegin(GL_TRIANGLES);
374 glColor4fv(MaterialShadow);
375 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlack);
376 glNormal3f(0.0, 1.0, 0.0);
379 glVertex3f(0.0, 0.0, -1.0);
380 glVertex3f(-sqrt(3.0)/2.0, 0.0, 0.5);
381 glVertex3f(sqrt(3.0)/2.0, 0.0, 0.5);
385 for(i = 0; i < 3; ++i) {
386 glRotatef(120.0, 0.0, 1.0, 0.0);
387 glBegin(GL_TRIANGLES);
388 glVertex3f(0.0, 0.0, 1.0 + 3.0);
389 glVertex3f(sqrt(3.0)/2.0, 0.0, -0.5 + 3.0);
390 glVertex3f(-sqrt(3.0)/2.0, 0.0, -0.5 + 3.0);
394 /* first render shadows -- no depth required */
397 shadowmatrix(m, ground, position0);
399 glColor4fv(MaterialShadow);
400 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
403 glDisable(GL_LIGHTING);
405 /* display ant shadow */
407 glTranslatef(0.0, 0.001, 0.0);
410 for(i = 0; i < ANTCOUNT; ++i) {
416 glRotatef(antposition[i], 0.0, 1.0, 0.0);
417 glTranslatef(2.4, 0.0, 0.0);
418 glTranslatef(0.0, antsphere[i], 0.0);
419 glRotatef(90.0, 0.0, 1.0, 0.0);
422 glRotatef(10.0, 0.0, 1.0, 0.0);
423 glRotatef(40.0, 0.0, 0.0, 1.0);
424 glTranslatef(0.0, -0.8, 0.0);
425 glRotatef(180.0, 0.0, 1.0, 0.0);
426 glRotatef(90.0, 0.0, 0.0, 1.0);
429 glColor4fv(MaterialShadow);
430 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
432 if(antposition[i] > 360.0)
433 antposition[i] = 0.0;
434 draw_antinspect_ant(mp, MaterialShadow, mono, mySphere2, myCone2);
437 glDisable(GL_LIGHTING);
440 glRotatef(-20.0, 1.0, 0.0, 0.0);
441 glRotatef(-ant_step*2, 0.0, 0.0, 1.0);
442 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
451 glEnable(GL_LIGHTING);
454 for(j = 0; j < ANTCOUNT; ++j) {
455 /* determine rendering order */
461 glRotatef(antposition[i], 0.0, 1.0, 0.0);
462 glTranslatef(2.4, 0.0, 0.0);
463 glTranslatef(0.0, antsphere[i], 0.0);
464 glRotatef(90.0, 0.0, 1.0, 0.0);
468 glRotatef(10.0, 0.0, 1.0, 0.0);
469 glRotatef(40.0, 0.0, 0.0, 1.0);
470 glTranslatef(0.0, -0.8, 0.0);
471 glRotatef(180.0, 0.0, 1.0, 0.0);
472 glRotatef(90.0, 0.0, 0.0, 1.0);
473 if(antposition[i] > 360.0)
474 antposition[i] = 0.0;
476 draw_antinspect_ant(mp, antmaterial[i], mono, mySphere2, myCone2);
481 glRotatef(-20.0, 1.0, 0.0, 0.0);
482 glRotatef(-ant_step*2, 0.0, 0.0, 1.0);
483 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mono ? MaterialGray5 : antmaterial[i]);
486 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlack);
492 /* finally, evolve */
493 antposition[i] += antvelocity[i];
496 /* but the step size is the same! */
499 mp->ant_position += 1;
503 void reshape_antinspect(ModeInfo * mi, int width, int height) {
504 double h = (GLfloat) height / (GLfloat) width;
505 antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
506 linewidth = (width / 512) + 1;
508 glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
509 glMatrixMode(GL_PROJECTION);
512 gluPerspective(45, 1/h, 7.0, 20.0);
514 glMatrixMode(GL_MODELVIEW);
515 glLineWidth(linewidth);
516 glPointSize(linewidth);
519 static void pinit(void) {
521 glClearColor(0.0, 0.0, 0.0, 1.0);
523 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
524 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
525 glLightfv(GL_LIGHT0, GL_POSITION, position0);
526 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
527 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
528 glLightfv(GL_LIGHT1, GL_POSITION, position1);
529 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
530 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
531 glEnable(GL_LIGHTING);
534 glEnable(GL_NORMALIZE);
538 glShadeModel(GL_SMOOTH);
539 glEnable(GL_DEPTH_TEST);
540 glDisable(GL_TEXTURE_2D);
542 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
543 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
546 void release_antinspect(ModeInfo * mi) {
548 free((void *) antinspect);
549 antinspect = (antinspectstruct *) NULL;
554 Bool antinspect_handle_event (ModeInfo *mi, XEvent *event) {
555 antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
557 if(event->xany.type == ButtonPress && event->xbutton.button == Button1) {
558 mp->button_down_p = True;
559 gltrackball_start(mp->trackball,
560 event->xbutton.x, event->xbutton.y,
561 MI_WIDTH (mi), MI_HEIGHT (mi));
564 else if(event->xany.type == ButtonRelease &&
565 event->xbutton.button == Button1) {
566 mp->button_down_p = False;
569 else if (event->xany.type == ButtonPress &&
570 (event->xbutton.button == Button4 ||
571 event->xbutton.button == Button5))
573 gltrackball_mousewheel (mp->trackball, event->xbutton.button, 5,
574 !event->xbutton.state);
577 else if(event->xany.type == MotionNotify && mp->button_down_p) {
578 gltrackball_track (mp->trackball,
579 event->xmotion.x, event->xmotion.y,
580 MI_WIDTH (mi), MI_HEIGHT (mi));
587 void init_antinspect(ModeInfo * mi) {
588 antinspectstruct *mp;
590 if(antinspect == NULL) {
591 if((antinspect = (antinspectstruct *) calloc(MI_NUM_SCREENS(mi),
592 sizeof (antinspectstruct))) == NULL)
595 mp = &antinspect[MI_SCREEN(mi)];
596 mp->step = NRAND(90);
597 mp->ant_position = NRAND(90);
598 mp->trackball = gltrackball_init ();
600 if ((mp->glx_context = init_GL(mi)) != NULL) {
601 reshape_antinspect(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
602 glDrawBuffer(GL_BACK);
608 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
611 void draw_antinspect(ModeInfo * mi) {
612 antinspectstruct *mp;
614 Display *display = MI_DISPLAY(mi);
615 Window window = MI_WINDOW(mi);
619 mp = &antinspect[MI_SCREEN(mi)];
621 MI_IS_DRAWN(mi) = True;
626 glXMakeCurrent(display, window, *(mp->glx_context));
628 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
632 /* position camera --- this works well, we can peer inside
634 glTranslatef(0.0, 0.0, -10.0);
635 gltrackball_rotate(mp->trackball);
636 glRotatef((15.0/2.0 + 15.0*sin(ant_step/100.0)), 1.0, 0.0, 0.0);
637 glRotatef(30.0, 1.0, 0.0, 0.0);
638 glRotatef(180.0, 0.0, 1.0, 0.0);
640 if (!draw_antinspect_strip(mi)) {
641 release_antinspect(mi);
647 if (MI_IS_FPS(mi)) do_fps (mi);
650 glXSwapBuffers(display, window);
655 void change_antinspect(ModeInfo * mi) {
656 antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
658 if (!mp->glx_context)
661 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));