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
17
#include <X11/Intrinsic.h>
20
#define PROGCLASS "Providence"
21
#define HACK_INIT init_providence
22
#define HACK_DRAW draw_providence
23
#define HACK_RESHAPE reshape_providence
24
#define HACK_HANDLE_EVENT providence_handle_event
25
#define EVENT_MASK PointerMotionMask
26
#define providence_opts xlockmore_opts
27
#define DEFAULTS "*delay: 20000 \n" \
28
"*showFPS: False \n" \
29
"*wireframe: False \n"
31
#include "xlockmore.h"
37
#include "gltrackball.h"
39
#define DEF_SOLIDPROVIDENCE "False"
40
#define DEF_EYE "True"
44
static XrmOptionDescRec opts[] = {
45
{"-eye", ".providence.eye", XrmoptionNoArg, "on"},
46
{"+eye", ".providence.eye", XrmoptionNoArg, "off"}
49
static argtype vars[] = {
50
{&eye, "eye", "Eye", DEF_EYE, t_Bool}
53
static OptionStruct desc[] = {
54
{"-/+eye", "turn on/off eye of providence"}
57
ModeSpecOpt providence_opts = {
58
sizeof opts / sizeof opts[0], opts,
59
sizeof vars / sizeof vars[0], vars, desc
63
ModStruct providence_description = {
64
"providence", "init_providence", "draw_providence",
65
"release_providence", "draw_providence", "change_providence",
66
(char *) NULL, &providence_opts, 1000, 1, 1, 1, 4, 1.0, "",
67
"draws pyramid with glory", 0, NULL
71
#define Scale4Window 0.3
72
#define Scale4Iconic 0.4
74
#define sqr(A) ((A)*(A))
80
int mono = 0, wire = 0;
81
double camera_velocity = 0.0;
82
double camera_z = -8.0;
87
GLXContext *glx_context;
88
trackball_state *trackball;
92
/* lighting variables */
93
GLfloat front_shininess[] = {60.0};
94
GLfloat front_specular[] = {0.2, 0.2, 0.2, 1.0};
95
GLfloat ambient[] = {0.8, 0.8, 0.8, 1.0};
96
GLfloat ambient2[] = {0.25, 0.25, 0.25, 1.0};
97
GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0};
98
GLfloat position0[] = {1.0, 5.0, 1.0, 1.0};
99
GLfloat position1[] = {-1.0, -5.0, 1.0, 1.0};
100
GLfloat lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
101
GLfloat lmodel_twoside[] = {GL_TRUE};
105
GLfloat MaterialGlory[] = {0.04, 0.30, 0.22, 0.7};
106
GLfloat MaterialGloryB[] = {0.07, 0.50, 0.36, 0.6};
108
GLfloat MaterialGloryF[] = {0.07, 0.50, 0.36, 1.0};
109
/* GLfloat MaterialGloryF[] = {0.06, 0.38, 0.27, 1.0}; */
110
GLfloat MaterialGloryE[] = {0.06, 0.38, 0.27, 0.3};
111
GLfloat MaterialGloryM[] = {0.5, 0.5, 0.5, 0.5};
112
GLfloat MaterialGloryMB[] = {0.36, 0.36, 0.36, 0.4};
113
GLfloat MaterialGreenback[4] = {0.04, 0.30, 0.22, 1.0};
114
GLfloat MaterialBlack[4] = {0.0, 0.0, 0.0, 1.0};
116
GLfloat MaterialGray5[] = {0.5, 0.5, 0.5, 1.0};
117
GLfloat MaterialGray6[] = {0.6, 0.6, 0.6, 1.0};
121
static providencestruct *providence = (providencestruct *) NULL;
126
#define checkImageWidth 64
127
#define checkImageHeight 64
128
GLubyte checkImage[checkImageWidth][checkImageHeight][3];
131
/* build brick texture */
132
void make_brick(void) {
135
for (i = 0; i < checkImageWidth; i++) {
136
for (j = 0; j < checkImageHeight; j++) {
137
c = i % 16 == 15 ? 255 : (j + 48*(i / 16))%64 == 0 ? 255 :
138
102 + random() % 102;
139
checkImage[i][j][0] = (GLubyte) c;
140
checkImage[i][j][1] = (GLubyte) c;
141
checkImage[i][j][2] = (GLubyte) c;
145
glGenTextures(1, &bricktexture);
146
glBindTexture(GL_TEXTURE_2D, bricktexture);
148
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
149
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
150
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
151
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
152
glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth,
153
checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,
155
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
159
int mini(int a, int b) { return a < b ? a : b; }
162
#define EYE_PARTICLE_COUNT 2000
163
int eyeparticles[EYE_PARTICLE_COUNT][2];
165
/* lookup table for the eye */
166
#define LOOKUPSIZE 3600
167
#define EYELENGTH 300
168
double lookup[LOOKUPSIZE][EYELENGTH][2];
169
double lookup2[LOOKUPSIZE][EYELENGTH][2];
171
/* build eye lookup table */
172
void build_eye(void) {
175
double inc = 0.1 / EYELENGTH;
176
double inc2 = 2.4*Pi / EYELENGTH;
178
/* describe all values tangentially out from pupil */
179
for(i = 0; i < LOOKUPSIZE; ++i) {
180
double r = i * 2*Pi / LOOKUPSIZE;/*x + inc;*/
185
for(j = 0; j < EYELENGTH; ++j) {
186
lookup[i][j][0] = x*sr;
187
lookup[i][j][1] = x*cr;
192
/* lookup2: dollar sign */
193
for(i = 0; i < LOOKUPSIZE; ++i) {
196
for(j = 0; j < EYELENGTH; ++j) {
198
lookup2[i][j][0] = sin(y)/6.0 + i/36000.0 - 0.05;
199
lookup2[i][j][1] = i%4 ? y/12.0 - 0.05 : 1.2*Pi-y/12.0 + 0.05;
202
lookup2[i][j][0] = i/36000.0 - 0.05;
203
lookup2[i][j][1] = y/9.0 - 0.05;
211
#define EPSILON 0.0001
213
double min(double a, double b) {
214
return a < b ? a : b;
217
double max(double a, double b) {
218
return a > b ? a : b;
221
#define PARTICLE_COUNT 2000
222
double particles[PARTICLE_COUNT][5];
224
void init_particle(double particle[5]) {
225
/* position along glory */
226
double p = (random() % 485410) / 100000.0;
232
particle[0] = p - 0.75;
233
particle[1] = -0.75001;
235
else if(p < 1.5 + sqrt(45)/4.0) {
237
particle[0] = 0.75 - d*cos(atan(2.0));
238
particle[1] = d*sin(atan(2.0)) - 0.75;
241
double d = 4.8541 - p;
242
particle[0] = -0.75 + d*cos(atan(2.0));
243
particle[1] = d*sin(atan(2.0)) - 0.75;
246
particle[3] = currenttime;
247
particle[4] = 1.25 + (random()%10)/10.0;
250
/* init glory particles */
251
void init_particles(void) {
253
for(i = 0; i < PARTICLE_COUNT; ++i) {
254
init_particle(particles[i]);
256
/* set initial time */
257
particles[i][3] = currenttime - (random()%1250)/1000.0;
260
/* init eye particles */
261
for(i = 0; i < EYE_PARTICLE_COUNT; ++i) {
262
eyeparticles[i][0] = random()%LOOKUPSIZE;
263
eyeparticles[i][1] = random()%EYELENGTH;
270
/* ugg, should be a priority queue if next event times known */
271
void update_particles(void) {
274
for(i = 0; i < PARTICLE_COUNT; ++i) {
275
/* check for time elapse */
276
if(currenttime > particles[i][3] + particles[i][4])
277
init_particle(particles[i]);
280
/* now update eye particles */
281
for(i = 0; i < EYE_PARTICLE_COUNT; ++i) {
282
/* int x = eyeparticles[i][1] + random()%16; */
283
int x = eyeparticles[i][1] + random()%(cos(theta) < 0.0 ? 8 : 16);
286
if(x > EYELENGTH || random()%(cos(theta) < 0.0 ? 40 : 10) == 0) {
288
/* if(x > EYELENGTH || (x > EYELENGTH/(2/3.0) && random()%7 == 0)) { */
289
eyeparticles[i][0] = random()%LOOKUPSIZE;
290
eyeparticles[i][1] = random()%40;
293
eyeparticles[i][1] = x;
298
/* draw the pyramid */
299
void draw_seal(void) {
301
double base = sqrt(2.0);
302
double top = 1.0 / sqrt(2.0);
303
double tmod = 7.0/6.0;
307
/* set options for mono, wireframe */
309
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
310
glDisable(GL_LIGHTING);
311
glDisable(GL_TEXTURE_2D);
314
glEnable(GL_TEXTURE_2D);
315
glBindTexture(GL_TEXTURE_2D, bricktexture);
317
glEnable(GL_LIGHTING);
319
glColor4fv(mono ? MaterialGray5 : MaterialGloryF);
320
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
321
mono ? MaterialGray5 : MaterialGloryF);
324
glRotatef(45.0, 0.0, 1.0, 0.0);
325
glTranslatef(0.0, -3.25, 0.0);
327
for(i = 0; i < 4; ++i) {
328
glRotatef(i*90.0, 0.0, 1.0, 0.0);
331
glNormal3f(1 / sqrt(6.0), 2 / sqrt(6.0), 1 / sqrt(6.0));
332
glTexCoord2f(-base, 0.0);
333
glVertex3f(-base, 0.0, base);
334
glTexCoord2f(base, 0.0);
335
glVertex3f(base, 0.0, base);
336
glTexCoord2f(top, 13.0/4.0);
337
glVertex3f(top, 2.0, top);
338
glTexCoord2f(-top, 13.0/4.0);
339
glVertex3f(-top, 2.0, top);
346
glNormal3f(0.0, 1.0, 0.0);
347
glTexCoord2f(0.02, 0.0);
348
glVertex3f(-top, 2.0, top);
349
glTexCoord2f(2.0*top, 0.0);
350
glVertex3f(top, 2.0, top);
351
glTexCoord2f(2.0*top, tmod*2.1*top);
352
glVertex3f(top, 2.0, -top);
353
glTexCoord2f(0.02, tmod*2.1*top);
354
glVertex3f(-top, 2.0, -top);
357
glNormal3f(0.0, -1.0, 0.0);
358
glTexCoord2f(-base, 0.0);
359
glVertex3f(-base, 0.0, -base);
360
glTexCoord2f(top, 0.0);
361
glVertex3f(base, 0.0, -base);
362
glTexCoord2f(top, top*13.0/4.0);
363
glVertex3f(base, 0.0, base);
364
glTexCoord2f(-top, top*13.0/4.0);
365
glVertex3f(-base, 0.0, base);
370
glDisable(GL_TEXTURE_2D);
374
void draw_glory(void) {
378
glBegin(GL_TRIANGLES);
379
glVertex3f(-0.75, -0.75, 0.0);
380
glVertex3f(0.75, -0.75, 0.0);
381
glVertex3f(0.0, 0.75, 0.0);
387
glDisable(GL_LIGHTING);
391
/* glory colour lines */
392
glColor4fv(mono ? MaterialGloryM : MaterialGlory);
393
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
394
mono ? MaterialGloryM : MaterialGlory);
397
for(i = 0; i < PARTICLE_COUNT/2; ++i) {
398
double t = currenttime - particles[i][3];
399
double th = atan(particles[i][1] / particles[i][0]);
400
if(particles[i][0] < 0.0)
403
glVertex3f(particles[i][0], particles[i][1], particles[i][2]);
404
glVertex3f(particles[i][0] + 0.2*cos(th)*t,
405
particles[i][1] + 0.2*sin(th)*t,
410
/* gloryb colour lines */
411
glColor4fv(mono ? MaterialGloryMB : MaterialGloryB);
412
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
413
mono ? MaterialGloryMB : MaterialGloryB);
415
for(; i < PARTICLE_COUNT; ++i) {
416
double t = currenttime - particles[i][3];
417
double th = atan(particles[i][1] / particles[i][0]);
418
if(particles[i][0] < 0.0)
421
glVertex3f(particles[i][0], particles[i][1], particles[i][2]);
422
glVertex3f(particles[i][0] + 0.2*cos(th)*t,
423
particles[i][1] + 0.2*sin(th)*t,
429
glEnable(GL_LIGHTING);
432
/* draw eye of providence */
433
void draw_eye(void) {
438
glBegin(GL_TRIANGLES);
439
glVertex3f(-0.25, -0.25, 0.0);
440
glVertex3f(0.25, -0.25, 0.0);
441
glVertex3f(0.0, 0.25, 0.0);
447
glDisable(GL_LIGHTING);
452
glColor4fv(mono ? MaterialGloryM : MaterialGlory);
453
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
454
mono ? MaterialGloryM : MaterialGlory);
456
/* draw eye particles on z = 0 plane */
458
for(i = 0; i < EYE_PARTICLE_COUNT/2; ++i) {
459
glVertex3f(lookup[eyeparticles[i][0]][eyeparticles[i][1]][0],
460
lookup[eyeparticles[i][0]][eyeparticles[i][1]][1],
466
glColor4fv(mono ? MaterialGloryMB : MaterialGloryB);
467
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
468
mono ? MaterialGloryMB : MaterialGloryB);
470
/* draw eye particles on z = 0 plane */
472
for(; i < EYE_PARTICLE_COUNT; ++i) {
473
glVertex3f(lookup[eyeparticles[i][0]][eyeparticles[i][1]][0],
474
lookup[eyeparticles[i][0]][eyeparticles[i][1]][1],
480
/* draw scaled particles */
482
glScalef(3.3, 2.2, 3.3);
485
glColor4fv(mono ? MaterialGloryMB : MaterialGloryB);
486
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
487
mono ? MaterialGloryMB : MaterialGloryB);
489
/* draw eye particles on z = 0 plane */
491
for(i = 0; i < EYE_PARTICLE_COUNT/2; ++i) {
492
glVertex3f(lookup[eyeparticles[i][0]][eyeparticles[i][1]][0],
493
lookup[eyeparticles[i][0]][eyeparticles[i][1]][1],
498
glColor4fv(mono ? MaterialGloryM : MaterialGlory);
499
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
500
mono ? MaterialGloryM : MaterialGlory);
502
/* draw eye particles on z = 0 plane */
504
for(; i < EYE_PARTICLE_COUNT; ++i) {
505
glVertex3f(lookup[eyeparticles[i][0]][eyeparticles[i][1]][0],
506
lookup[eyeparticles[i][0]][eyeparticles[i][1]][1],
514
glEnable(GL_LIGHTING);
517
/* draw eye of providence */
518
void draw_eye2(void) {
523
glBegin(GL_TRIANGLES);
524
glVertex3f(-0.25, -0.25, 0.0);
525
glVertex3f(0.25, -0.25, 0.0);
526
glVertex3f(0.0, 0.25, 0.0);
532
glDisable(GL_LIGHTING);
537
glColor4fv(mono ? MaterialGloryM : MaterialGlory);
538
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
539
mono ? MaterialGloryM : MaterialGlory);
541
/* draw eye particles on z = 0 plane */
543
for(i = 0; i < EYE_PARTICLE_COUNT/2; ++i) {
544
glVertex3f(lookup2[eyeparticles[i][0]][eyeparticles[i][1]][0],
545
lookup2[eyeparticles[i][0]][eyeparticles[i][1]][1],
551
glColor4fv(mono ? MaterialGloryMB : MaterialGloryB);
552
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
553
mono ? MaterialGloryMB : MaterialGloryB);
555
/* draw eye particles on z = 0 plane */
557
for(; i < EYE_PARTICLE_COUNT; ++i) {
558
glVertex3f(lookup2[eyeparticles[i][0]][eyeparticles[i][1]][0],
559
lookup2[eyeparticles[i][0]][eyeparticles[i][1]][1],
565
glEnable(GL_LIGHTING);
569
void draw_providence_strip(ModeInfo *mi) {
570
glTranslatef(0.0, 1.414, 0.0);
572
position0[0] = 1.6*sin(theta);
574
position0[2] = 1.6*cos(theta);
576
glLightfv(GL_LIGHT0, GL_POSITION, position0);
577
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient2);
578
glEnable(GL_LIGHTING);
581
/* draw pyramid, glory */
583
glCallList(pyramidlist);
595
void reshape_providence(ModeInfo * mi, int width, int height) {
596
double h = (GLfloat) height / (GLfloat) width;
597
providencestruct *mp = &providence[MI_SCREEN(mi)];
599
glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
600
glMatrixMode(GL_PROJECTION);
603
gluPerspective(45, 1/h, 0.001, 25.0);
605
glMatrixMode(GL_MODELVIEW);
610
static void pinit(void) {
612
glClearColor(0.0, 0.0, 0.0, 1.0);
614
/* setup twoside lighting */
615
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient2);
616
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
617
glLightfv(GL_LIGHT0, GL_POSITION, position0);
619
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
620
glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
621
glEnable(GL_LIGHTING);
629
glEnable(GL_NORMALIZE);
631
/* glDisable(GL_CULL_FACE); */
632
glEnable(GL_CULL_FACE);
634
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
636
glShadeModel(GL_SMOOTH);
637
glEnable(GL_DEPTH_TEST);
638
glDepthFunc(GL_LEQUAL);
640
/* build pyramid list */
641
pyramidlist = glGenLists(1);
642
glNewList(pyramidlist, GL_COMPILE);
647
/* cleanup routine */
648
void release_providence(ModeInfo * mi) {
651
free((void *) providence);
652
providence = (providencestruct *) NULL;
659
Bool providence_handle_event(ModeInfo *mi, XEvent *event) {
660
providencestruct *mp = &providence[MI_SCREEN(mi)];
662
switch(event->xany.type) {
665
switch(event->xbutton.button) {
668
mp->button_down_p = True;
669
gltrackball_start(mp->trackball,
670
event->xbutton.x, event->xbutton.y,
671
MI_WIDTH (mi), MI_HEIGHT (mi));
675
camera_velocity += 1.0;
679
camera_velocity -= 1.0;
687
switch(event->xbutton.button) {
689
mp->button_down_p = False;
696
if(mp->button_down_p)
697
gltrackball_track(mp->trackball,
698
event->xmotion.x, event->xmotion.y,
699
MI_WIDTH (mi), MI_HEIGHT (mi));
709
void init_providence(ModeInfo *mi) {
710
providencestruct *mp;
713
if((providence = (providencestruct *)
714
calloc(MI_NUM_SCREENS(mi), sizeof (providencestruct))) == NULL)
717
mp = &providence[MI_SCREEN(mi)];
718
mp->trackball = gltrackball_init ();
720
mono = MI_IS_MONO(mi);
721
wire = MI_IS_WIREFRAME(mi);
723
if((mp->glx_context = init_GL(mi)) != NULL) {
724
reshape_providence(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
725
glDrawBuffer(GL_BACK);
732
void draw_providence(ModeInfo * mi) {
733
providencestruct *mp;
735
Display *display = MI_DISPLAY(mi);
736
Window window = MI_WINDOW(mi);
740
mp = &providence[MI_SCREEN(mi)];
742
MI_IS_DRAWN(mi) = True;
747
glXMakeCurrent(display, window, *(mp->glx_context));
749
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
754
if(fabs(camera_velocity) > EPSILON) {
755
camera_z = max(min(camera_z + 0.1*camera_velocity, -4.0), -12.0);
756
camera_velocity = 0.95*camera_velocity;
759
/* rotate providence */
760
glTranslatef(0.0, 0.0, camera_z + sin(theta/4.0));
761
glRotatef(10.0+20.0*sin(theta/2.0), 1.0, 0.0, 0.0);
762
gltrackball_rotate(mp->trackball);
763
glRotatef(theta * 180.0 / Pi, 0.0, -1.0, 0.0);
765
/* draw providence */
766
draw_providence_strip(mi);
769
if(MI_IS_FPS(mi)) do_fps (mi);
772
glXSwapBuffers(display, window);
775
currenttime += 1.0 / FPS;
776
theta = currenttime / 2.0;
780
void change_providence(ModeInfo * mi) {
781
providencestruct *mp = &providence[MI_SCREEN(mi)];
783
if (!mp->glx_context)
786
glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));