1 /* blinkbox, Copyright (c) 2003 Jeremy English <jenglish@myself.com>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 /* motion blur added March 2005 by John Boero <jlboero@cs.uwm.edu>
15 #define DEFAULTS "*delay: 30000 \n" \
16 "*wireframe: False \n" \
17 "*suppressRotationAnimation: True\n" \
19 # define release_ball 0
20 # define ball_handle_event xlockmore_no_events
22 #include "xlockmore.h"
26 #ifdef USE_GL /* whole file */
29 #define ALPHA_AMT 0.05
31 /* this should be between 1 and 8 */
32 #define DEF_BOXSIZE "2"
33 #define DEF_DISSOLVE "False"
34 #define DEF_FADE "True"
35 #define DEF_BLUR "True"
65 GLfloat wh; /*width Height*/
69 static const struct Bounding_box bbox = {{14,14,20},{-14,-14,-20}};
72 GLXContext *glx_context;
79 Tdpos moh; /*hold motion value*/
98 static blinkboxstruct *blinkbox = (blinkboxstruct *) NULL;
102 static const float LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
103 static const float LightPosition[]= { 20.0f, 100.0f, 20.0f, 1.0f };
105 static Bool do_dissolve;
108 static float bscale_wh;
110 static XrmOptionDescRec opts[] = {
111 { "-boxsize", ".boxsize", XrmoptionSepArg, 0 },
112 { "-dissolve", ".dissolve", XrmoptionNoArg, "True" },
113 { "+dissolve", ".dissolve", XrmoptionNoArg, "False" },
114 { "-fade", ".fade", XrmoptionNoArg, "True" },
115 { "+fade", ".fade", XrmoptionNoArg, "False" },
116 { "-blur", ".blur", XrmoptionNoArg, "True" },
117 { "+blur", ".blur", XrmoptionNoArg, "False" }
121 static argtype vars[] = {
122 {&bscale_wh, "boxsize", "Boxsize", DEF_BOXSIZE, t_Float},
123 {&do_dissolve, "dissolve", "Dissolve", DEF_DISSOLVE, t_Bool},
124 {&do_fade, "fade", "Fade", DEF_FADE, t_Bool},
125 {&do_blur, "blur", "Blur", DEF_BLUR, t_Bool},
128 ENTRYPOINT ModeSpecOpt ball_opts = {countof(opts), opts, countof(vars), vars, NULL};
131 swap(GLfloat *a, GLfloat *b)
141 GLfloat j = 1+(random() % 2);
146 swap_mov(GLfloat *a, GLfloat *b)
158 cp_b_pos(blinkboxstruct *bp, Tdpos *s_pos)
160 s_pos->x = bp->ball.x;
161 s_pos->y = bp->ball.y;
162 s_pos->z = bp->ball.z;
166 hit_side(blinkboxstruct *bp)
168 if ((bp->ball.x - bp->ball.d) <= bbox.bottom.x){
170 bp->lside.counter = MAX_COUNT;
171 bp->lside.des_count = 1;
172 bp->lside.alpha_count = 0;
173 cp_b_pos(bp, &bp->lside.pos);
174 swap_mov(&bp->mo.x,&bp->moh.x);
176 if ((bp->ball.x + bp->ball.d) >= bbox.top.x){
178 bp->rside.counter = MAX_COUNT;
179 bp->rside.des_count = 1;
180 bp->rside.alpha_count = 0;
181 cp_b_pos(bp, &bp->rside.pos);
182 swap_mov(&bp->mo.x,&bp->moh.x);
187 hit_top_bottom(blinkboxstruct *bp)
189 if ((bp->ball.y - bp->ball.d) <= bbox.bottom.y){
191 bp->bside.counter = MAX_COUNT;
192 bp->bside.des_count = 1;
193 bp->bside.alpha_count = 0;
194 cp_b_pos(bp, &bp->bside.pos);
195 swap_mov(&bp->mo.y,&bp->moh.y);
197 if ((bp->ball.y + bp->ball.d) >= bbox.top.y){
199 bp->tside.counter = MAX_COUNT;
200 bp->tside.des_count = 1;
201 bp->tside.alpha_count = 0;
202 cp_b_pos(bp, &bp->tside.pos);
203 swap_mov(&bp->mo.y,&bp->moh.y);
208 hit_front_back(blinkboxstruct *bp)
210 if ((bp->ball.z - bp->ball.d) <= bbox.bottom.z){
212 bp->aside.counter = MAX_COUNT;
213 bp->aside.des_count = 1;
214 bp->aside.alpha_count = 0;
215 cp_b_pos(bp, &bp->aside.pos);
216 swap_mov(&bp->mo.z,&bp->moh.z);
218 if((bp->ball.z + bp->ball.d) >= bbox.top.z){
220 bp->fside.counter = MAX_COUNT;
221 bp->fside.des_count = 1;
222 bp->fside.alpha_count = 0;
223 cp_b_pos(bp, &bp->fside.pos);
224 swap_mov(&bp->mo.z,&bp->moh.z);
229 reshape_ball (ModeInfo *mi, int width, int height)
231 GLfloat h = (GLfloat) height / (GLfloat) width;
234 if (width > height * 5) { /* tiny window: show middle */
235 height = width * 9/16;
237 h = height / (GLfloat) width;
240 glViewport (0, y, (GLint) width, (GLint) height);
241 glMatrixMode(GL_PROJECTION);
243 gluPerspective (30.0, 1/h, 1.0, 100.0);
245 glMatrixMode(GL_MODELVIEW);
247 gluLookAt( 0.0, 0.0, 40.0,
255 glBegin((wire)?GL_LINE_LOOP:GL_QUADS);
256 glNormal3f( 0.0f, -1.0f, 0.0f);
257 glVertex3f(-1.0f, -1.0f, -1.0f);
258 glVertex3f( 1.0f, -1.0f, -1.0f);
259 glVertex3f( 1.0f, -1.0f, 1.0f);
260 glVertex3f(-1.0f, -1.0f, 1.0f);
261 glNormal3f( 0.0f, 0.0f, 1.0f);
262 glVertex3f(-1.0f, -1.0f, 1.0f);
263 glVertex3f( 1.0f, -1.0f, 1.0f);
264 glVertex3f( 1.0f, 1.0f, 1.0f);
265 glVertex3f(-1.0f, 1.0f, 1.0f);
266 glNormal3f( 0.0f, 0.0f, -1.0f);
267 glVertex3f(-1.0f, -1.0f, -1.0f);
268 glVertex3f(-1.0f, 1.0f, -1.0f);
269 glVertex3f( 1.0f, 1.0f, -1.0f);
270 glVertex3f( 1.0f, -1.0f, -1.0f);
271 glNormal3f( 1.0f, 0.0f, 0.0f);
272 glVertex3f( 1.0f, -1.0f, -1.0f);
273 glVertex3f( 1.0f, 1.0f, -1.0f);
274 glVertex3f( 1.0f, 1.0f, 1.0f);
275 glVertex3f( 1.0f, -1.0f, 1.0f);
276 glNormal3f( -1.0f, 0.0f, 0.0f);
277 glVertex3f(-1.0f, -1.0f, -1.0f);
278 glVertex3f(-1.0f, -1.0f, 1.0f);
279 glVertex3f(-1.0f, 1.0f, 1.0f);
280 glVertex3f(-1.0f, 1.0f, -1.0f);
281 glNormal3f( 1.0f, 1.0f, 0.0f);
282 glVertex3f(-1.0f, 1.0f, -1.0f);
283 glVertex3f(-1.0f, 1.0f, 1.0f);
284 glVertex3f( 1.0f, 1.0f, 1.0f);
285 glVertex3f( 1.0f, 1.0f, -1.0f);
290 init_ball (ModeInfo *mi)
292 int wire = MI_IS_WIREFRAME(mi);
295 MI_INIT (mi, blinkbox);
296 bp = &blinkbox[MI_SCREEN(mi)];
298 if ((bp->glx_context = init_GL(mi)) != NULL) {
299 reshape_ball(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
300 glDrawBuffer(GL_BACK);
306 bp->bscale.wh = bscale_wh;
323 bp->lside.counter = MAX_COUNT;
324 bp->rside.counter = MAX_COUNT;
325 bp->tside.counter = MAX_COUNT;
326 bp->bside.counter = MAX_COUNT;
327 bp->fside.counter = MAX_COUNT;
328 bp->aside.counter = MAX_COUNT;
330 bp->lside.color[0] = 1;
331 bp->rside.color[1] = 1;
332 bp->tside.color[2] = 1;
334 bp->bside.color[0] = 1;
335 bp->bside.color[1] = 0.5;
337 bp->fside.color[0] = 1;
338 bp->fside.color[1] = 1;
340 bp->aside.color[0] = 0.5;
341 bp->aside.color[2] = 1;
343 bp->lside.rot[0] = 90;
344 bp->rside.rot[0] = 90;
345 bp->tside.rot[0] = 90;
346 bp->bside.rot[0] = 90;
347 bp->fside.rot[0] = 90;
348 bp->aside.rot[0] = 90;
350 bp->lside.rot[2] = 1;
351 bp->rside.rot[2] = 1;
352 bp->tside.rot[1] = 1;
353 bp->bside.rot[1] = 1;
354 bp->fside.rot[3] = 1;
355 bp->aside.rot[3] = 1;
357 bp->lside.des_count = 1;
358 bp->rside.des_count = 1;
359 bp->tside.des_count = 1;
360 bp->bside.des_count = 1;
361 bp->fside.des_count = 1;
362 bp->aside.des_count = 1;
364 bp->lside.alpha_count = 1;
365 bp->rside.alpha_count = 1;
366 bp->tside.alpha_count = 1;
367 bp->bside.alpha_count = 1;
368 bp->fside.alpha_count = 1;
369 bp->aside.alpha_count = 1;
372 #define SPHERE_SLICES 12 /* how densely to render spheres */
373 #define SPHERE_STACKS 16
375 /* bp->sp = malloc(sizeof(*bp->sp));
377 fprintf(stderr,"Could not allocate memory\n");
380 if( (bp->bscale.wh < 1) ||
381 (bp->bscale.wh > 8) ) {
382 fprintf(stderr,"Boxsize out of range. Using default\n");
386 bp->des_amt = bp->bscale.wh / MAX_COUNT;
389 reshape_ball(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
390 bp->ballList = glGenLists(1);
391 glNewList(bp->ballList, GL_COMPILE);
392 unit_sphere (SPHERE_STACKS, SPHERE_SLICES, wire);
395 bp->boxList = glGenLists(1);
396 glNewList(bp->boxList, GL_COMPILE);
402 glEnable(GL_COLOR_MATERIAL);
403 glShadeModel(GL_SMOOTH);
405 glEnable(GL_DEPTH_TEST);
406 glDepthFunc(GL_LEQUAL);
407 glEnable(GL_LIGHTING);
409 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
410 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
412 if (do_fade || do_blur) {
414 glDisable(GL_DEPTH_TEST);
419 CheckBoxPos(blinkboxstruct *bp,
420 GLfloat bot_x, GLfloat top_x, GLfloat bot_y, GLfloat top_y)
422 /*Make sure it's inside of the bounding box*/
423 bp->bpos.x = ((bp->bpos.x - bp->bscale.wh) < bot_x) ? bot_x + bp->bscale.wh : bp->bpos.x;
424 bp->bpos.x = ((bp->bpos.x + bp->bscale.wh) > top_x) ? top_x - bp->bscale.wh : bp->bpos.x;
425 bp->bpos.y = ((bp->bpos.y - bp->bscale.wh) < bot_y) ? bot_y + bp->bscale.wh : bp->bpos.y;
426 bp->bpos.y = ((bp->bpos.y + bp->bscale.wh) > top_y) ? top_y - bp->bscale.wh : bp->bpos.y;
430 draw_ball (ModeInfo *mi)
432 blinkboxstruct *bp = &blinkbox[MI_SCREEN(mi)];
434 Display *dpy = MI_DISPLAY(mi);
435 Window window = MI_WINDOW(mi);
438 if (! bp->glx_context)
440 mi->polygon_count = 0;
441 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
443 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
449 glRotated(0.25,0,0,1);
450 glRotated(0.25,0,1,0);
451 glRotated(0.25,1,0,0);
457 GLfloat s = (MI_WIDTH(mi) < MI_HEIGHT(mi)
458 ? MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi)
467 if (!do_blur || MI_IS_WIREFRAME(mi)) {
468 glTranslatef(bp->ball.x += bp->mo.x,
469 bp->ball.y += bp->mo.y,
470 bp->ball.z += bp->mo.z);
473 glCallList(bp->ballList);
474 mi->polygon_count += SPHERE_SLICES*SPHERE_STACKS;
478 # define blur_detail 24.0
479 float ball_alpha = 1 / blur_detail;
481 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
482 glTranslatef(bp->ball.x, bp->ball.y, bp->ball.z);
484 for (i = 0; i < blur_detail; ++i) {
485 glTranslatef(bp->mo.x / blur_detail,
486 bp->mo.y / blur_detail,
487 bp->mo.z / blur_detail);
489 /* comment the following line for quick but boring linear blur */
490 ball_alpha = sin((M_PI / blur_detail) * i) / blur_detail;
492 glColor4f(1, 1, 1, ball_alpha);
495 glCallList(bp->ballList);
496 mi->polygon_count += SPHERE_SLICES*SPHERE_STACKS;
497 glScalef(.5, .5, .5);
501 bp->ball.x += bp->mo.x;
502 bp->ball.y += bp->mo.y;
503 bp->ball.z += bp->mo.z;
512 bp->bpos.x = bp->lside.pos.z*-1;
513 bp->bpos.y = bp->lside.pos.y;
514 bp->bpos.z = bbox.bottom.x - bp->bscale.d;
516 CheckBoxPos(bp, bbox.bottom.z,bbox.top.z,bbox.bottom.y,bbox.top.y);
521 bp->bpos.x = bp->rside.pos.z*-1;
522 bp->bpos.y = bp->rside.pos.y;
523 bp->bpos.z = bbox.top.x + bp->bscale.d;
525 CheckBoxPos(bp, bbox.bottom.z,bbox.top.z,bbox.bottom.y,bbox.top.y);
530 bp->bpos.x = bp->tside.pos.x;
531 bp->bpos.y = bp->tside.pos.z;
532 bp->bpos.z = bbox.bottom.y - bp->bscale.d;
534 CheckBoxPos(bp, bbox.bottom.x,bbox.top.x,bbox.bottom.z,bbox.top.z);
539 bp->bpos.x = bp->bside.pos.x;
540 bp->bpos.y = bp->bside.pos.z;
541 bp->bpos.z = bbox.top.y + bp->bscale.d;
543 CheckBoxPos(bp, bbox.bottom.x,bbox.top.x,bbox.bottom.z,bbox.top.z);
548 bp->bpos.x = bp->fside.pos.y;
549 bp->bpos.y = bp->fside.pos.x*-1;
550 bp->bpos.z = bbox.top.z + bp->bscale.d;
552 CheckBoxPos(bp, bbox.bottom.y,bbox.top.y,bbox.bottom.x,bbox.top.x);
557 bp->bpos.x = bp->aside.pos.y;
558 bp->bpos.y = bp->aside.pos.x*-1;
559 bp->bpos.z = bbox.bottom.z + bp->bscale.d;
561 CheckBoxPos(bp, bbox.bottom.y,bbox.top.y,bbox.bottom.x,bbox.top.x);
567 glColor4f(bp->sp->color[0],bp->sp->color[1],bp->sp->color[2],1-(ALPHA_AMT * bp->sp->alpha_count));
569 glColor3fv(bp->sp->color);
571 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
573 glRotatef(bp->sp->rot[0],bp->sp->rot[1],bp->sp->rot[2],bp->sp->rot[3]);
574 glTranslatef(bp->bpos.x,bp->bpos.y,bp->bpos.z);
576 glScalef(bp->bscale.wh-(bp->des_amt*bp->sp->des_count),bp->bscale.wh-(bp->des_amt*bp->sp->des_count),bp->bscale.d);
578 glScalef(bp->bscale.wh,bp->bscale.wh,bp->bscale.d);
580 glCallList(bp->boxList);
581 mi->polygon_count += 6;
585 bp->sp->alpha_count++;
596 if (mi->fps_p) do_fps (mi);
598 glXSwapBuffers(dpy, window);
603 free_ball (ModeInfo *mi)
605 blinkboxstruct *bp = &blinkbox[MI_SCREEN(mi)];
606 if (!bp->glx_context) return;
607 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
608 if (glIsList(bp->ballList)) glDeleteLists(bp->ballList, 1);
609 if (glIsList(bp->boxList)) glDeleteLists(bp->boxList, 1);
612 XSCREENSAVER_MODULE_2 ("BlinkBox", blinkbox, ball)