X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Flament.c;h=fecf80982457d88df0b0b3d26a2d3ee8b05e7365;hp=3f5080c04d0b0b0650b988c7df94d29c732c7850;hb=ffd8c0873576a9e3065696a624dce6b766b77062;hpb=3c58fb6311db49c46f1670922933b27c6ea0c065 diff --git a/hacks/glx/lament.c b/hacks/glx/lament.c index 3f5080c0..fecf8098 100644 --- a/hacks/glx/lament.c +++ b/hacks/glx/lament.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1998 Jamie Zawinski +/* xscreensaver, Copyright (c) 1998-2004 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 @@ -67,13 +67,6 @@ * Needs music. ("Hellraiser Themes" by Coil: TORSO CD161; also duplicated on the "Unnatural History 2" compilation, WORLN M04699.) - - * I'm not totally happy with the spinning motion; I like the - acceleration and deceleration, but it often feels like it's going too - fast, or not naturally enough, or something. - - * However, the motion is better than that used by gears, superquadrics, - etc.; so maybe I should make them all share the same motion code. */ #include @@ -82,8 +75,10 @@ #define HACK_INIT init_lament #define HACK_DRAW draw_lament #define HACK_RESHAPE reshape_lament +#define HACK_HANDLE_EVENT lament_handle_event +#define EVENT_MASK PointerMotionMask #define lament_opts xlockmore_opts -#define DEFAULTS "*delay: 10000 \n" \ +#define DEFAULTS "*delay: 20000 \n" \ "*showFPS: False \n" \ "*wireframe: False \n" \ "*texture: True \n" @@ -98,17 +93,19 @@ static int do_texture; static XrmOptionDescRec opts[] = { - {"-texture", ".lament.texture", XrmoptionNoArg, (caddr_t) "true" }, - {"+texture", ".lament.texture", XrmoptionNoArg, (caddr_t) "false" }, + {"-texture", ".lament.texture", XrmoptionNoArg, "true" }, + {"+texture", ".lament.texture", XrmoptionNoArg, "false" }, }; static argtype vars[] = { - {(caddr_t *) &do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, }; ModeSpecOpt lament_opts = {countof(opts), opts, countof(vars), vars, NULL}; #include "xpm-ximage.h" +#include "rotator.h" +#include "gltrackball.h" #include "../images/lament.xpm" #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) @@ -154,6 +151,10 @@ static GLfloat interior_color[] = { 0.20, 0.20, 0.15, 1.00, /* ambient */ typedef struct { GLXContext *glx_context; + rotator *rot; + double rotx, roty, rotz; + trackball_state *trackball; + Bool button_down_p; GLuint box; /* display list IDs */ GLuint star1, star2; @@ -161,10 +162,6 @@ typedef struct { GLuint lid_0, lid_1, lid_2, lid_3, lid_4; GLuint taser_base, taser_lifter, taser_slider; - GLfloat rotx, roty, rotz; /* current object rotation */ - GLfloat dx, dy, dz; /* current rotational velocity */ - GLfloat ddx, ddy, ddz; /* current rotational acceleration */ - GLfloat d_max; /* max velocity */ XImage *texture; /* image bits */ GLuint texids[6]; /* texture map IDs */ lament_type type; /* which mode of the object is current */ @@ -194,92 +191,83 @@ parse_image_data(ModeInfo *mi) } -/* Computing normal vectors (thanks to Nat Friedman ) - */ - -typedef struct vector { - GLfloat x, y, z; -} vector; - -typedef struct plane { - vector p1, p2, p3; -} plane; - -static void -vector_set(vector *v, GLfloat x, GLfloat y, GLfloat z) -{ - v->x = x; - v->y = y; - v->z = z; -} +typedef struct { + double x,y,z; +} XYZ; static void -vector_cross(vector v1, vector v2, vector *v3) +normalize (XYZ *p) { - v3->x = (v1.y * v2.z) - (v1.z * v2.y); - v3->y = (v1.z * v2.x) - (v1.x * v2.z); - v3->z = (v1.x * v2.y) - (v1.y * v2.x); + double length; + length = sqrt (p->x * p->x + + p->y * p->y + + p->z * p->z); + if (length != 0) + { + p->x /= length; + p->y /= length; + p->z /= length; + } + else + { + p->x = 0; + p->y = 0; + p->z = 0; + } } -static void -vector_subtract(vector v1, vector v2, vector *res) +/* Calculate the unit normal at p given two other points p1,p2 on the + surface. The normal points in the direction of p1 crossproduct p2 + */ +static XYZ +calc_normal (XYZ p, XYZ p1, XYZ p2) { - res->x = v1.x - v2.x; - res->y = v1.y - v2.y; - res->z = v1.z - v2.z; + XYZ n, pa, pb; + pa.x = p1.x - p.x; + pa.y = p1.y - p.y; + pa.z = p1.z - p.z; + pb.x = p2.x - p.x; + pb.y = p2.y - p.y; + pb.z = p2.z - p.z; + n.x = pa.y * pb.z - pa.z * pb.y; + n.y = pa.z * pb.x - pa.x * pb.z; + n.z = pa.x * pb.y - pa.y * pb.x; + normalize (&n); + return (n); } -static void -plane_normal(plane p, vector *n) -{ - vector v1, v2; - vector_subtract(p.p1, p.p2, &v1); - vector_subtract(p.p1, p.p3, &v2); - vector_cross(v2, v1, n); -} static void do_normal(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2, GLfloat x3, GLfloat y3, GLfloat z3) { - plane plane; - vector n; - vector_set(&plane.p1, x1, y1, z1); - vector_set(&plane.p2, x2, y2, z2); - vector_set(&plane.p3, x3, y3, z3); - plane_normal(plane, &n); - n.x = -n.x; n.y = -n.y; n.z = -n.z; + XYZ p1, p2, p3, p; + p1.x = x1; p1.y = y1; p1.z = z1; + p2.x = x2; p2.y = y2; p2.z = z2; + p3.x = x3; p3.y = y3; p3.z = z3; + + p = calc_normal (p1, p2, p3); - glNormal3f(n.x, n.y, n.z); + glNormal3f (p.x, p.y, p.z); #ifdef DEBUG /* Draw a line in the direction of this face's normal. */ { - GLfloat ax = n.x > 0 ? n.x : -n.x; - GLfloat ay = n.y > 0 ? n.y : -n.y; - GLfloat az = n.z > 0 ? n.z : -n.z; - GLfloat mx = (x1 + x2 + x3) / 3; - GLfloat my = (y1 + y2 + y3) / 3; - GLfloat mz = (z1 + z2 + z3) / 3; - GLfloat xx, yy, zz; - - GLfloat max = ax > ay ? ax : ay; - if (az > max) max = az; - max *= 2; - xx = n.x / max; - yy = n.y / max; - zz = n.z / max; - + glPushMatrix(); + glTranslatef ((x1 + x2 + x3) / 3, + (y1 + y2 + y3) / 3, + (z1 + z2 + z3) / 3); + glScalef (0.5, 0.5, 0.5); glBegin(GL_LINE_LOOP); - glVertex3f(mx, my, mz); - glVertex3f(mx+xx, my+yy, mz+zz); + glVertex3f(0, 0, 0); + glVertex3f(p.x, p.y, p.z); glEnd(); + glPopMatrix(); } #endif /* DEBUG */ } - /* Shorthand utilities for making faces, with proper normals. */ @@ -1403,6 +1391,39 @@ taser(ModeInfo *mi, Bool wire) /* Rendering and animating object models */ +Bool +lament_handle_event (ModeInfo *mi, XEvent *event) +{ + lament_configuration *lc = &lcs[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + event->xbutton.button & Button1) + { + lc->button_down_p = True; + gltrackball_start (lc->trackball, + event->xbutton.x, event->xbutton.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + else if (event->xany.type == ButtonRelease && + event->xbutton.button & Button1) + { + lc->button_down_p = False; + return True; + } + else if (event->xany.type == MotionNotify && + lc->button_down_p) + { + gltrackball_track (lc->trackball, + event->xmotion.x, event->xmotion.y, + MI_WIDTH (mi), MI_HEIGHT (mi)); + return True; + } + + return False; +} + + static void draw(ModeInfo *mi) { @@ -1415,24 +1436,14 @@ draw(ModeInfo *mi) glClear(GL_COLOR_BUFFER_BIT); glPushMatrix(); - { - GLfloat x = lc->rotx; - GLfloat y = lc->roty; - GLfloat z = lc->rotz; - -#if 0 - x=0.75; y=0; z=0; -#endif - if (x < 0) x = 1 - (x + 1); - if (y < 0) y = 1 - (y + 1); - if (z < 0) z = 1 - (z + 1); + gltrackball_rotate (lc->trackball); - /* Make into the screen be +Y right be +X, and up be +Z. */ - glRotatef(-90.0, 1.0, 0.0, 0.0); + /* 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 it up. */ + glScalef(4.0, 4.0, 4.0); #ifdef DEBUG glPushMatrix(); @@ -1458,9 +1469,12 @@ draw(ModeInfo *mi) glPushMatrix(); { /* Apply rotation to the object. */ - glRotatef(x * 360, 1.0, 0.0, 0.0); - glRotatef(y * 360, 0.0, 1.0, 0.0); - glRotatef(z * 360, 0.0, 0.0, 1.0); + if (lc->type != LAMENT_LID_ZOOM) + get_rotation (lc->rot, &lc->rotx, &lc->roty, &lc->rotz, + !lc->button_down_p); + glRotatef (lc->rotx * 360, 1.0, 0.0, 0.0); + glRotatef (lc->roty * 360, 0.0, 1.0, 0.0); + glRotatef (lc->rotz * 360, 0.0, 0.0, 1.0); switch (lc->type) { @@ -1570,7 +1584,6 @@ draw(ModeInfo *mi) } glPopMatrix(); - } glPopMatrix(); } @@ -1764,9 +1777,6 @@ animate(ModeInfo *mi) { lc->anim_r = 0.0; lc->anim_z = 0.0; - lc->rotx = frand(1.0) * RANDSIGN(); - lc->roty = frand(1.0) * RANDSIGN(); - lc->rotz = frand(1.0) * RANDSIGN(); lc->type = LAMENT_BOX; } break; @@ -1820,73 +1830,6 @@ animate(ModeInfo *mi) } -static void -rotate(GLfloat *pos, GLfloat *v, GLfloat *dv, GLfloat max_v) -{ - double ppos = *pos; - - /* tick position */ - if (ppos < 0) - ppos = -(ppos + *v); - else - ppos += *v; - - if (ppos > 1.0) - ppos -= 1.0; - else if (ppos < 0) - ppos += 1.0; - - if (ppos < 0) abort(); - if (ppos > 1.0) abort(); - *pos = (*pos > 0 ? ppos : -ppos); - - /* accelerate */ - *v += *dv; - - /* clamp velocity */ - if (*v > max_v || *v < -max_v) - { - *dv = -*dv; - } - /* If it stops, start it going in the other direction. */ - else if (*v < 0) - { - if (random() % 4) - { - *v = 0; - - /* keep going in the same direction */ - if (random() % 2) - *dv = 0; - else if (*dv < 0) - *dv = -*dv; - } - else - { - /* reverse gears */ - *v = -*v; - *dv = -*dv; - *pos = -*pos; - } - } - - /* Alter direction of rotational acceleration randomly. */ - if (! (random() % 120)) - *dv = -*dv; - - /* Change acceleration very occasionally. */ - if (! (random() % 200)) - { - if (*dv == 0) - *dv = 0.00001; - else if (random() & 1) - *dv *= 1.2; - else - *dv *= 0.8; - } -} - - /* Window management, etc */ @@ -1918,7 +1861,7 @@ reshape_lament(ModeInfo *mi, int width, int height) 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 pixellated. + a 1024x1024 animation that looks really pixelated. */ if (win_size > target_size * 1.5) { @@ -1993,7 +1936,9 @@ gl_init(ModeInfo *mi) clear_gl_error(); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lc->texture->width, height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, + GL_RGBA, + /* GL_UNSIGNED_BYTE, */ + GL_UNSIGNED_INT_8_8_8_8_REV, (lc->texture->data + (lc->texture->bytes_per_line * height * i))); check_gl_error("texture"); @@ -2099,20 +2044,11 @@ init_lament(ModeInfo *mi) lc = &lcs[MI_SCREEN(mi)]; - lc->rotx = frand(1.0) * RANDSIGN(); - lc->roty = frand(1.0) * RANDSIGN(); - lc->rotz = frand(1.0) * RANDSIGN(); - - /* bell curve from 0-1.5 degrees, avg 0.75 */ - lc->dx = (frand(1) + frand(1) + frand(1)) / (360*2); - lc->dy = (frand(1) + frand(1) + frand(1)) / (360*2); - lc->dz = (frand(1) + frand(1) + frand(1)) / (360*2); - - lc->d_max = lc->dx * 2; - - lc->ddx = 0.00006 + frand(0.00003); - lc->ddy = 0.00006 + frand(0.00003); - lc->ddz = 0.00006 + frand(0.00003); + { + double rot_speed = 0.5; + lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True); + lc->trackball = gltrackball_init (); + } lc->type = LAMENT_BOX; lc->anim_pause = 300 + (random() % 100); @@ -2148,13 +2084,6 @@ draw_lament(ModeInfo *mi) glFinish(); glXSwapBuffers(dpy, window); - if (lc->type != LAMENT_LID_ZOOM) - { - rotate(&lc->rotx, &lc->dx, &lc->ddx, lc->d_max); - rotate(&lc->roty, &lc->dy, &lc->ddy, lc->d_max); - rotate(&lc->rotz, &lc->dz, &lc->ddz, lc->d_max); - } - if (lc->anim_pause) lc->anim_pause--; else