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" \
29 "*showFPS: False \n" \
30 "*wireframe: False \n"
32 #include "xlockmore.h"
38 #include "gltrackball.h"
40 #define DEF_SHADOWS "True"
44 static XrmOptionDescRec opts[] = {
45 {"-shadows", ".antinspect.shadows", XrmoptionNoArg, "on"},
46 {"+shadows", ".antinspect.shadows", XrmoptionNoArg, "off"}
49 static argtype vars[] = {
50 {&shadows, "shadows", "Shadows", DEF_SHADOWS, t_Bool}
53 static OptionStruct desc[] = {
54 {"-/+shadows", "turn on/off ant shadows"}
57 ModeSpecOpt antinspect_opts = {sizeof opts / sizeof opts[0],
59 sizeof vars / sizeof vars[0],
64 ModStruct antinspect_description =
65 {"antinspect", "init_antinspect", "draw_antinspect", "release_antinspect",
66 "draw_antinspect", "change_antinspect", (char *) NULL, &antinspect_opts,
67 1000, 1, 1, 1, 4, 1.0, "",
68 "draws some ants", 0, NULL};
71 #define Scale4Window 0.3
72 #define Scale4Iconic 0.4
74 #define sqr(A) ((A)*(A))
80 #define ObjAntinspectStrip 0
84 /*************************************************************************/
90 GLXContext *glx_context;
91 trackball_state *trackball;
95 static float front_shininess[] = {60.0};
96 static float front_specular[] = {0.7, 0.7, 0.7, 1.0};
97 static float ambient[] = {0.0, 0.0, 0.0, 1.0};
98 static float diffuse[] = {1.0, 1.0, 1.0, 1.0};
99 static float position0[] = {0.0, 3.0, 0.0, 1.0};
100 static float position1[] = {-1.0, -3.0, 1.0, 0.0};
101 static float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
102 static float lmodel_twoside[] = {GL_TRUE};
104 static float MaterialRed[] = {0.6, 0.0, 0.0, 1.0};
105 static float MaterialOrange[] = {1.0, 0.69, 0.00, 1.0};
106 static float MaterialGray[] = {0.2, 0.2, 0.2, 1.0};
107 static float MaterialBlack[] = {0.1, 0.1, 0.1, 0.4};
108 static float MaterialShadow[] = {0.3, 0.3, 0.3, 0.3};
109 static float MaterialGray5[] = {0.5, 0.5, 0.5, 0.3};
110 static float MaterialGray6[] = {0.6, 0.6, 0.6, 1.0};
112 static antinspectstruct *antinspect = (antinspectstruct *) NULL;
119 /* create a matrix that will project the desired shadow */
120 void shadowmatrix(GLfloat shadowMat[4][4],
121 GLfloat groundplane[4],
122 GLfloat lightpos[4]) {
125 /* find dot product between light position vector and ground plane normal */
126 dot = groundplane[X] * lightpos[X] +
127 groundplane[Y] * lightpos[Y] +
128 groundplane[Z] * lightpos[Z] +
129 groundplane[W] * lightpos[W];
131 shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
132 shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
133 shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
134 shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
136 shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
137 shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
138 shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
139 shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
141 shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
142 shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
143 shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
144 shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
146 shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
147 shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
148 shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
149 shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
152 GLfloat ground[4] = {0.0, 1.0, 0.0, -0.00001};
154 /* simple filled sphere */
155 static Bool mySphere(float radius) {
156 GLUquadricObj *quadObj;
158 if((quadObj = gluNewQuadric()) == 0)
160 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
161 gluSphere(quadObj, radius, 16, 16);
162 gluDeleteQuadric(quadObj);
168 static Bool mySphere2(float radius) {
169 GLUquadricObj *quadObj;
171 if((quadObj = gluNewQuadric()) == 0)
173 gluQuadricDrawStyle(quadObj, (GLenum) GLU_LINE);/*GLU_SILHOUETTE);*/
174 gluSphere(quadObj, radius, 16, 8);
175 gluDeleteQuadric(quadObj);
181 static Bool myCone2(float radius) {
186 static float ant_step = 0;
189 static Bool draw_antinspect_ant(antinspectstruct * mp, float *Material, int mono,
190 Bool (*sphere)(float), Bool (*cone)(float)) {
191 float cos1 = cos(ant_step);
192 float cos2 = cos(ant_step + 2 * Pi / 3);
193 float cos3 = cos(ant_step + 4 * Pi / 3);
194 float sin1 = sin(ant_step);
195 float sin2 = sin(ant_step + 2 * Pi / 3);
196 float sin3 = sin(ant_step + 4 * Pi / 3);
199 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
201 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Material);
202 glEnable(GL_CULL_FACE);
205 if (!((*sphere)(0.18)))
207 glScalef(1, 1 / 1.3, 1);
208 glTranslatef(0.00, 0.30, 0.00);
209 if (!((*sphere)(0.2)))
212 glTranslatef(-0.05, 0.17, 0.05);
213 glRotatef(-90, 1, 0, 0);
214 glRotatef(-25, 0, 1, 0);
215 if (!((*cone)(0.05)))
217 glTranslatef(0.00, 0.10, 0.00);
218 if (!((*cone)(0.05)))
220 glRotatef(25, 0, 1, 0);
221 glRotatef(90, 1, 0, 0);
224 glTranslatef(0.15, -0.65, 0.05);
225 if (!((*sphere)(0.25)))
227 glScalef(1, 1 / 1.3, 1);
229 glDisable(GL_CULL_FACE);
231 glDisable(GL_LIGHTING);
236 glColor3fv(MaterialGray5);
238 glColor3fv(Material);
239 glVertex3f(0.00, 0.30, 0.00);
240 glColor3fv(MaterialGray);
241 glVertex3f(0.40, 0.70, 0.40);
243 glColor3fv(MaterialGray5);
245 glColor3fv(Material);
246 glVertex3f(0.00, 0.30, 0.00);
247 glColor3fv(MaterialGray);
248 glVertex3f(0.40, 0.70, -0.40);
252 glColor3fv(MaterialGray6);
254 glColor3fv(Material);
255 glVertex3f(0.40, 0.70, 0.40);
256 glVertex3f(0.40, 0.70, -0.40);
260 glBegin(GL_LINE_STRIP);
262 glColor3fv(MaterialGray5);
264 glColor3fv(Material);
265 glVertex3f(0.00, 0.05, 0.18);
266 glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25);
267 glColor3fv(MaterialGray);
268 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
271 /* LEFT-CENTER ARM */
272 glBegin(GL_LINE_STRIP);
274 glColor3fv(MaterialGray5);
276 glColor3fv(Material);
277 glVertex3f(0.00, 0.00, 0.18);
278 glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25);
279 glColor3fv(MaterialGray);
280 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
284 glBegin(GL_LINE_STRIP);
286 glColor3fv(MaterialGray5);
288 glColor3fv(Material);
289 glVertex3f(0.00, -0.05, 0.18);
290 glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25);
291 glColor3fv(MaterialGray);
292 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
295 /* RIGHT-FRONT ARM */
296 glBegin(GL_LINE_STRIP);
298 glColor3fv(MaterialGray5);
300 glColor3fv(Material);
301 glVertex3f(0.00, 0.05, -0.18);
302 glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25);
303 glColor3fv(MaterialGray);
304 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
307 /* RIGHT-CENTER ARM */
308 glBegin(GL_LINE_STRIP);
310 glColor3fv(MaterialGray5);
312 glColor3fv(Material);
313 glVertex3f(0.00, 0.00, -0.18);
314 glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25);
315 glColor3fv(MaterialGray);
316 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
320 glBegin(GL_LINE_STRIP);
322 glColor3fv(MaterialGray5);
324 glColor3fv(Material);
325 glVertex3f(0.00, -0.05, -0.18);
326 glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25);
327 glColor3fv(MaterialGray);
328 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
331 glEnable(GL_LIGHTING);
336 /* only works with 3 right now */
339 float MaterialBen[4] = {0.25, 0.30, 0.46, 1.0};
341 static float* antmaterial[ANTCOUNT] =
342 {MaterialRed, MaterialBen, MaterialOrange};
343 static double antposition[ANTCOUNT] = {0.0, 120.0, 240.0};
344 static double antvelocity[ANTCOUNT] = {0.3, 0.3, 0.3};
345 static double antsphere[ANTCOUNT] = {1.2, 1.2, 1.2};
348 static double antorder[6][ANTCOUNT] = {{0, 1, 2},
356 static Bool draw_antinspect_strip(ModeInfo * mi) {
357 antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
359 int mono = MI_IS_MONO(mi);
361 int ro = (((int)antposition[1])/(360/(2*ANTCOUNT))) % (2*ANTCOUNT);
363 glEnable(GL_TEXTURE_2D);
365 glLightfv(GL_LIGHT0, GL_POSITION, position0);
367 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
368 glRotatef(-30.0, 0.0, 1.0, 0.0);
370 glDisable(GL_TEXTURE_2D);
373 /* render ground plane */
374 glBegin(GL_TRIANGLES);
375 glColor4fv(MaterialShadow);
376 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlack);
377 glNormal3f(0.0, 1.0, 0.0);
380 glVertex3f(0.0, 0.0, -1.0);
381 glVertex3f(-sqrt(3.0)/2.0, 0.0, 0.5);
382 glVertex3f(sqrt(3.0)/2.0, 0.0, 0.5);
386 for(i = 0; i < 3; ++i) {
387 glRotatef(120.0, 0.0, 1.0, 0.0);
388 glBegin(GL_TRIANGLES);
389 glVertex3f(0.0, 0.0, 1.0 + 3.0);
390 glVertex3f(sqrt(3.0)/2.0, 0.0, -0.5 + 3.0);
391 glVertex3f(-sqrt(3.0)/2.0, 0.0, -0.5 + 3.0);
395 /* first render shadows -- no depth required */
398 shadowmatrix(m, ground, position0);
400 glColor4fv(MaterialShadow);
401 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
404 glDisable(GL_LIGHTING);
406 /* display ant shadow */
408 glTranslatef(0.0, 0.001, 0.0);
411 for(i = 0; i < ANTCOUNT; ++i) {
417 glRotatef(antposition[i], 0.0, 1.0, 0.0);
418 glTranslatef(2.4, 0.0, 0.0);
419 glTranslatef(0.0, antsphere[i], 0.0);
420 glRotatef(90.0, 0.0, 1.0, 0.0);
423 glRotatef(10.0, 0.0, 1.0, 0.0);
424 glRotatef(40.0, 0.0, 0.0, 1.0);
425 glTranslatef(0.0, -0.8, 0.0);
426 glRotatef(180.0, 0.0, 1.0, 0.0);
427 glRotatef(90.0, 0.0, 0.0, 1.0);
430 glColor4fv(MaterialShadow);
431 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
433 if(antposition[i] > 360.0)
434 antposition[i] = 0.0;
435 draw_antinspect_ant(mp, MaterialShadow, mono, mySphere2, myCone2);
438 glDisable(GL_LIGHTING);
441 glRotatef(-20.0, 1.0, 0.0, 0.0);
442 glRotatef(-ant_step*2, 0.0, 0.0, 1.0);
443 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
452 glEnable(GL_LIGHTING);
455 for(j = 0; j < ANTCOUNT; ++j) {
456 /* determine rendering order */
462 glRotatef(antposition[i], 0.0, 1.0, 0.0);
463 glTranslatef(2.4, 0.0, 0.0);
464 glTranslatef(0.0, antsphere[i], 0.0);
465 glRotatef(90.0, 0.0, 1.0, 0.0);
469 glRotatef(10.0, 0.0, 1.0, 0.0);
470 glRotatef(40.0, 0.0, 0.0, 1.0);
471 glTranslatef(0.0, -0.8, 0.0);
472 glRotatef(180.0, 0.0, 1.0, 0.0);
473 glRotatef(90.0, 0.0, 0.0, 1.0);
474 if(antposition[i] > 360.0)
475 antposition[i] = 0.0;
477 draw_antinspect_ant(mp, antmaterial[i], mono, mySphere2, myCone2);
482 glRotatef(-20.0, 1.0, 0.0, 0.0);
483 glRotatef(-ant_step*2, 0.0, 0.0, 1.0);
484 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mono ? MaterialGray5 : antmaterial[i]);
487 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlack);
493 /* finally, evolve */
494 antposition[i] += antvelocity[i];
497 /* but the step size is the same! */
500 mp->ant_position += 1;
504 void reshape_antinspect(ModeInfo * mi, int width, int height) {
505 double h = (GLfloat) height / (GLfloat) width;
506 antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
507 linewidth = (width / 512) + 1;
509 glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
510 glMatrixMode(GL_PROJECTION);
513 gluPerspective(45, 1/h, 7.0, 20.0);
515 glMatrixMode(GL_MODELVIEW);
516 glLineWidth(linewidth);
517 glPointSize(linewidth);
520 static void pinit(void) {
522 glClearColor(0.0, 0.0, 0.0, 1.0);
524 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
525 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
526 glLightfv(GL_LIGHT0, GL_POSITION, position0);
527 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
528 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
529 glLightfv(GL_LIGHT1, GL_POSITION, position1);
530 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
531 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
532 glEnable(GL_LIGHTING);
535 glEnable(GL_NORMALIZE);
539 glShadeModel(GL_SMOOTH);
540 glEnable(GL_DEPTH_TEST);
541 glDisable(GL_TEXTURE_2D);
543 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
544 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
547 void release_antinspect(ModeInfo * mi) {
549 free((void *) antinspect);
550 antinspect = (antinspectstruct *) NULL;
555 Bool antinspect_handle_event (ModeInfo *mi, XEvent *event) {
556 antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
558 if(event->xany.type == ButtonPress && event->xbutton.button == Button1) {
559 mp->button_down_p = True;
560 gltrackball_start(mp->trackball,
561 event->xbutton.x, event->xbutton.y,
562 MI_WIDTH (mi), MI_HEIGHT (mi));
565 else if(event->xany.type == ButtonRelease &&
566 event->xbutton.button == Button1) {
567 mp->button_down_p = False;
570 else if (event->xany.type == ButtonPress &&
571 (event->xbutton.button == Button4 ||
572 event->xbutton.button == Button5))
574 gltrackball_mousewheel (mp->trackball, event->xbutton.button, 5,
575 !event->xbutton.state);
578 else if(event->xany.type == MotionNotify && mp->button_down_p) {
579 gltrackball_track (mp->trackball,
580 event->xmotion.x, event->xmotion.y,
581 MI_WIDTH (mi), MI_HEIGHT (mi));
588 void init_antinspect(ModeInfo * mi) {
589 antinspectstruct *mp;
591 if(antinspect == NULL) {
592 if((antinspect = (antinspectstruct *) calloc(MI_NUM_SCREENS(mi),
593 sizeof (antinspectstruct))) == NULL)
596 mp = &antinspect[MI_SCREEN(mi)];
597 mp->step = NRAND(90);
598 mp->ant_position = NRAND(90);
599 mp->trackball = gltrackball_init ();
601 if ((mp->glx_context = init_GL(mi)) != NULL) {
602 reshape_antinspect(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
603 glDrawBuffer(GL_BACK);
609 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
612 void draw_antinspect(ModeInfo * mi) {
613 antinspectstruct *mp;
615 Display *display = MI_DISPLAY(mi);
616 Window window = MI_WINDOW(mi);
620 mp = &antinspect[MI_SCREEN(mi)];
622 MI_IS_DRAWN(mi) = True;
627 glXMakeCurrent(display, window, *(mp->glx_context));
629 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
633 /* position camera --- this works well, we can peer inside
635 glTranslatef(0.0, 0.0, -10.0);
636 gltrackball_rotate(mp->trackball);
637 glRotatef((15.0/2.0 + 15.0*sin(ant_step/100.0)), 1.0, 0.0, 0.0);
638 glRotatef(30.0, 1.0, 0.0, 0.0);
639 glRotatef(180.0, 0.0, 1.0, 0.0);
641 if (!draw_antinspect_strip(mi)) {
642 release_antinspect(mi);
648 if (MI_IS_FPS(mi)) do_fps (mi);
651 glXSwapBuffers(display, window);
656 void change_antinspect(ModeInfo * mi) {
657 antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
659 if (!mp->glx_context)
662 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));