X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fglx%2Flament.c;h=ab4bf83e1109ca7d472c34538b13459a8202f401;hb=6f5482d73adb0165c0130bb47d852644ab0c4869;hp=7c6f4b8a211ae6fa380b63d158107e1199627811;hpb=49f5b54f312fe4ac2e9bc47581a72451bd0e8439;p=xscreensaver diff --git a/hacks/glx/lament.c b/hacks/glx/lament.c index 7c6f4b8a..ab4bf83e 100644 --- a/hacks/glx/lament.c +++ b/hacks/glx/lament.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1998-2004 Jamie Zawinski +/* xscreensaver, Copyright (c) 1998-2012 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -17,14 +17,19 @@ "gold" to me. * For some reason, the interior surfaces are shinier than the exterior - surfaces. I don't understand why, but this should be remedied. + surfaces. Not sure why. - * Perhaps use a slightly-bumpy or oily texture for the interior surfaces? + * Should use a dark wood-grain texture for the interior surfaces. - * Some of the edges don't line up perfectly (since the images are not - perfectly symetrical.) Something should be done about this; either - making the edges overlap slightly (instead of leaving gaps) or fixing - the images so that the edges may be symmetrical. + * Building a face out of multiple adjacent triangles was a terrible + idea and leads to visible seams. Should re-do the face generation + to make all of them out of a single triangle strip instead. + + * The coordinates are slightly off from the image. lament512.gif is the + "right" one, and "lament512b.gif" is the image corrected to line up + with what the code is actually doing. + + * The "star" slices really don't line up well. * I want the gold leaf to seem to be raised up from the surface, but I think this isn't possible with OpenGL. Supposedly, OpenGL only @@ -32,18 +37,6 @@ and shading smoothly) but bump-maps only work with Phong shading (computing a normal for each rendered pixel.) - * As far as I can tell, OpenGL doesn't do shadows. As a result, the - forward-facing interior walls are drawn bright, not dark. If it was - casting shadows properly, it wouldn't matter so much that the edges - don't quite line up, because the lines would be black, and thus not - visible. But the edges don't match up, and so the bright interior - faces show through, and that sucks. - - But apparently there are tricky ways around this: - http://reality.sgi.com/opengl/tips/rts/ - I think these techniques require GLUT, however, which isn't - (currently) required by any other xscreensaver hacks. - * There should be strange lighting effects playing across the surface: electric sparks, or little glittery blobs of light. http://reality.sgi.com/opengl/tips/lensflare/ might provide guidance. @@ -62,9 +55,6 @@ to use (or that look like they would take any less than several months to become even marginally proficient with...) - * Perhaps there should be a table top, on which it casts a shadow? - And then multiple light sources (for multiple shadows)? - * Needs music. ("Hellraiser Themes" by Coil: TORSO CD161; also duplicated on the "Unnatural History 2" compilation, WORLN M04699.) */ @@ -100,7 +90,11 @@ ENTRYPOINT ModeSpecOpt lament_opts = {countof(opts), opts, countof(vars), vars, #include "xpm-ximage.h" #include "rotator.h" #include "gltrackball.h" -#include "../images/lament.xpm" +#if 0 +# include "../images/lament128.xpm" +#else +# include "../images/lament512.xpm" +#endif #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) #define RANDSIGN() ((random() & 1) ? 1 : -1) @@ -164,6 +158,7 @@ typedef struct { int anim_pause; /* countdown before animating again */ GLfloat anim_r, anim_y, anim_z; /* relative position during anims */ + Bool facing_p; int state, nstates; lament_type *states; @@ -329,8 +324,8 @@ star(ModeInfo *mi, Bool top, Bool wire) int i; int points[][2] = { - { 77, 74 }, { 60, 98 }, { 0, 71 }, { 0, 0 }, /* L1 */ - { 60, 98 }, { 55, 127 }, { 0, 127 }, { 0, 71 }, /* L2 */ + { 77, 74 }, { 60, 99 }, { 0, 74 }, { 0, 0 }, /* L1 */ + { 60, 99 }, { 55, 127 }, { 0, 127 }, { 0, 74 }, /* L2 */ { 55, 127 }, { 60, 154 }, { 0, 179 }, { 0, 127 }, /* L3 */ { 60, 154 }, { 76, 176 }, { 0, 255 }, { 0, 179 }, /* L4 */ { 76, 176 }, { 100, 193 }, { 74, 255 }, { 0, 255 }, /* B1 */ @@ -1334,7 +1329,9 @@ lament_handle_event (ModeInfo *mi, XEvent *event) } else if (event->xany.type == ButtonPress && (event->xbutton.button == Button4 || - event->xbutton.button == Button5)) + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) { gltrackball_mousewheel (lc->trackball, event->xbutton.button, 5, !!event->xbutton.state); @@ -1353,6 +1350,65 @@ lament_handle_event (ModeInfo *mi, XEvent *event) } +static void +check_facing(ModeInfo *mi) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + + GLdouble m[16], p[16], x, y, z; + GLint v[4]; + glGetDoublev (GL_MODELVIEW_MATRIX, m); + glGetDoublev (GL_PROJECTION_MATRIX, p); + glGetIntegerv (GL_VIEWPORT, v); + + /* See if a coordinate 5 units in front of the door is near the + center of the screen. */ + + gluProject (-5, 0, 0, m, p, v, &x, &y, &z); + x = (x / MI_WIDTH(mi)) - 0.5; + y = (y / MI_HEIGHT(mi)) - 0.5; + lc->facing_p = (z < 0.9 && + x > -0.02 && x < 0.02 && + y > -0.02 && y < 0.02); +} + + + +static void +scale_for_window(ModeInfo *mi) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + int target_size = lc->texture->width * 1.4; + int win_size = (MI_WIDTH(mi) > MI_HEIGHT(mi) ? MI_HEIGHT(mi) : MI_WIDTH(mi)); + + /* This scale makes the box take up most of the window */ + glScalef(8, 8, 8); + + /* But if the window is more than a little larger than our target size, + scale the object back down, so that the bits drawn on the screen end + up rougly target_size across (actually it ends up a little larger.) + Note that the image-map bits we have are 128x128. Therefore, if the + image is magnified a lot, it looks pretty blocky. So it's better to + have a 128x128 animation on a 1280x1024 screen that looks good, than + a 1024x1024 animation that looks really pixelated. + */ + + { + int max = 340; /* Let's not go larger than life-sized. */ + if (target_size > max) + target_size = max; + } + + if (win_size > 640 && + win_size > target_size * 1.5) + { + GLfloat ratio = ((GLfloat) target_size / (GLfloat) win_size); + ratio *= 2.0; + glScalef(ratio, ratio, ratio); + } +} + + static void draw(ModeInfo *mi) { @@ -1366,15 +1422,17 @@ draw(ModeInfo *mi) glPushMatrix(); + /* Do it twice because we don't track the device's orientation. */ + glRotatef( current_device_rotation(), 0, 0, 1); gltrackball_rotate (lc->trackball); + glRotatef(-current_device_rotation(), 0, 0, 1); /* Make into the screen be +Y right be +X, and up be +Z. */ glRotatef(-90.0, 1.0, 0.0, 0.0); - /* Scale it up. */ - glScalef(4.0, 4.0, 4.0); + scale_for_window (mi); -#ifdef DEBUG +#if 0 glPushMatrix(); { /* Shift to the upper left, and draw the vanilla box. */ @@ -1392,7 +1450,7 @@ draw(ModeInfo *mi) /* Shift to the lower right, and draw the animated object. */ glTranslatef(0.6, 0.0, -0.6); -#endif /* DEBUG */ +#endif /* 0 */ glPushMatrix(); @@ -1405,6 +1463,8 @@ draw(ModeInfo *mi) glRotatef (lc->roty * 360, 0.0, 1.0, 0.0); glRotatef (lc->rotz * 360, 0.0, 0.0, 1.0); + check_facing(mi); + switch (lc->type) { case LAMENT_BOX: @@ -1660,28 +1720,11 @@ animate(ModeInfo *mi) if (lc->anim_r >= 112.0) { - GLfloat hysteresis = 0.05; - lc->anim_r = 112.0; lc->anim_z = 0.0; lc->anim_pause = pause3; - - if (lc->rotx >= -hysteresis && - lc->rotx <= hysteresis && - ((lc->rotz >= (0.25 - hysteresis) && - lc->rotz <= (0.25 + hysteresis)) || - (lc->rotz >= (-0.25 - hysteresis) && - lc->rotz <= (-0.25 + hysteresis)))) - { - lc->type = LAMENT_LID_ZOOM; - lc->rotx = 0.00; - lc->rotz = (lc->rotz < 0 ? -0.25 : 0.25); - } - else - { - lc->type = LAMENT_LID_CLOSE; - } - } + lc->type = (lc->facing_p ? LAMENT_LID_ZOOM : LAMENT_LID_CLOSE); + } break; case LAMENT_LID_CLOSE: @@ -1760,42 +1803,15 @@ animate(ModeInfo *mi) ENTRYPOINT void reshape_lament(ModeInfo *mi, int width, int height) { - int target_size = 180; - int win_size = (width > height ? height : width); GLfloat h = (GLfloat) height / (GLfloat) width; - glViewport(0, 0, (GLint) width, (GLint) height); -/* glViewport(-600, -600, 1800, 1800); */ - glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -40.0); - - /* This scale makes the box take up most of the window */ - glScalef(2.0, 2.0, 2.0); - - /* But if the window is more than a little larger than our target size, - scale the object back down, so that the bits drawn on the screen end - up rougly target_size across (actually it ends up a little larger.) - Note that the image-map bits we have are 128x128. Therefore, if the - image is magnified a lot, it looks pretty blocky. So it's better to - have a 128x128 animation on a 1280x1024 screen that looks good, than - a 1024x1024 animation that looks really pixelated. - */ - if (win_size > target_size * 1.5) - { - GLfloat ratio = ((GLfloat) target_size / (GLfloat) win_size); - ratio *= 2.0; - glScalef(ratio, ratio, ratio); - } - - /* The depth buffer will be cleared, if needed, before the - * next frame. Right now we just want to black the screen. - */ glClear(GL_COLOR_BUFFER_BIT); } @@ -1848,7 +1864,8 @@ gl_init(ModeInfo *mi) parse_image_data(mi); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width); + /* messes up -fps */ + /* glPixelStorei(GL_UNPACK_ROW_LENGTH, lc->texture->width); */ for (i = 0; i < 6; i++) { @@ -1870,8 +1887,6 @@ gl_init(ModeInfo *mi) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); } #else /* !HAVE_GLBINDTEXTURE */