diff options
| author | Simon Rettberg | 2024-09-06 14:42:37 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2024-09-06 14:42:37 +0200 |
| commit | badef32037f52f79abc1f1440b786cd71afdf270 (patch) | |
| tree | 412b792d4cab4a7a110db82fcf74fe8a1ac55ec1 /hacks/glx/vigilance.c | |
| parent | Delete pre-6.00 files (diff) | |
| download | xscreensaver-master.tar.gz xscreensaver-master.tar.xz xscreensaver-master.zip | |
Diffstat (limited to 'hacks/glx/vigilance.c')
| -rw-r--r-- | hacks/glx/vigilance.c | 1170 |
1 files changed, 0 insertions, 1170 deletions
diff --git a/hacks/glx/vigilance.c b/hacks/glx/vigilance.c deleted file mode 100644 index a3add18..0000000 --- a/hacks/glx/vigilance.c +++ /dev/null @@ -1,1170 +0,0 @@ -/* vigilance, Copyright (c) 2017-2018 Jamie Zawinski <jwz@jwz.org> - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * Draws surveillance cameras, taking an interest in their surroundings. - */ - -#define DEFAULTS "*delay: 20000 \n" \ - "*count: 5 \n" \ - "*showFPS: False \n" \ - "*wireframe: False \n" \ - "*bodyColor: #666666" "\n" \ - "*capColor: #FFFFFF" "\n" \ - "*hingeColor: #444444" "\n" \ - "*mountColor: #444444" "\n" \ - "*lensColor: #000000" "\n" \ - "*groundColor: #004400" "\n" \ - -# define release_camera 0 - -#define DEF_SPEED "1.0" -#define DEF_CAMERA_SIZE "1.0" - -#include "xlockmore.h" -#include "gltrackball.h" -#include "ximage-loader.h" -#include "normals.h" - -#include <ctype.h> - -#ifdef USE_GL /* whole file */ - -#undef ABS -#define ABS(x) ((x)<0?-(x):(x)) -#undef MAX -#define MAX(A,B) ((A)>(B)?(A):(B)) -#undef MIN -#define MIN(A,B) ((A)<(B)?(A):(B)) -#undef BELLRAND -#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) - -#include "gllist.h" - -extern const struct gllist - *seccam_body, *seccam_cap, *seccam_hinge, *seccam_pipe, *seccam_lens; -static struct gllist *ground = 0; - -static const struct gllist * const *all_objs[] = { - &seccam_body, &seccam_cap, &seccam_hinge, &seccam_pipe, &seccam_lens, - (const struct gllist * const *) &ground -}; - -#define CAMERA_BODY 0 -#define CAMERA_CAP 1 -#define CAMERA_HINGE 2 -#define CAMERA_MOUNT 3 -#define CAMERA_LENS 4 -#define GROUND 5 - -#define BEAM_ZOFF 0.185 /* distance from origin to lens in model */ - -typedef enum { IDLE, WARM_UP, ZOT, COOL_DOWN } camera_state; - - -typedef struct { - XYZ pos; - GLfloat facing; /* rotation around vertical axis, degrees */ - GLfloat pitch; /* front/back tilt, degrees */ - GLfloat velocity; /* most recent angular velocity, degrees */ - long focus_id; /* pedestrian or camera of interest */ - XYZ focus; /* point of interest */ - camera_state state; - GLfloat tick; -} camera; - -typedef struct pedestrian pedestrian; -struct pedestrian { - long id; - XYZ pos; - GLfloat length; - GLfloat frequency, amplitude; - GLfloat ratio; - GLfloat speed; - pedestrian *next; -}; - -typedef struct { - GLXContext *glx_context; - trackball_state *user_trackball; - Bool button_down_p; - - GLuint *dlists; - GLfloat component_colors[countof(all_objs)][4]; - - int ncameras; - camera *cameras; - pedestrian *pedestrians; -} camera_configuration; - -static camera_configuration *bps = NULL; - -static GLfloat speed_arg; -#ifdef DEBUG -static int debug_p; -#endif - -static XrmOptionDescRec opts[] = { - { "-speed", ".speed", XrmoptionSepArg, 0 }, -#ifdef DEBUG - {"-debug", ".debug", XrmoptionNoArg, "True" }, - {"+debug", ".debug", XrmoptionNoArg, "False" }, -#endif -}; - -static argtype vars[] = { - {&speed_arg, "speed", "Speed", DEF_SPEED, t_Float}, -#ifdef DEBUG - {&debug_p, "debug", "Debug", "False", t_Bool}, -#endif -}; - -ENTRYPOINT ModeSpecOpt camera_opts = { - countof(opts), opts, countof(vars), vars, NULL}; - - -ENTRYPOINT void -reshape_camera (ModeInfo *mi, int width, int height) -{ - GLfloat h = (GLfloat) height / (GLfloat) width; - int y = 0; - - if (width > height * 5) { /* tiny window: show middle */ - height = width * 9/16; - y = -height/2; - h = height / (GLfloat) width; - } - - glViewport (0, y, width, height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective (30.0, 1/h, 1.0, 200); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - gluLookAt( 0, 0, 30, - 0, 0, 0, - 0, 1, 0); - - { - GLfloat s = (MI_WIDTH(mi) < MI_HEIGHT(mi) - ? (MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi)) - : 1); - glScalef (s, s, s); - } - - glClear(GL_COLOR_BUFFER_BIT); -} - - -ENTRYPOINT Bool -camera_handle_event (ModeInfo *mi, XEvent *event) -{ - camera_configuration *bp = &bps[MI_SCREEN(mi)]; - - if (gltrackball_event_handler (event, bp->user_trackball, - MI_WIDTH (mi), MI_HEIGHT (mi), - &bp->button_down_p)) - return True; - else if (event->xany.type == KeyPress) - { - KeySym keysym; - char c = 0; - XLookupString (&event->xkey, &c, 1, &keysym, 0); - if (c == ' ' || c == '\t') - { - int i; - if (bp->cameras[0].state == IDLE && bp->pedestrians) - for (i = 0; i < bp->ncameras; i++) - { - bp->cameras[i].state = WARM_UP; - bp->cameras[i].tick = 1.0; - } - return True; - } - } - - return False; -} - - -static int draw_ground (ModeInfo *, GLfloat color[4]); - -static void -parse_color (ModeInfo *mi, char *key, GLfloat color[4]) -{ - XColor xcolor; - char *string = get_string_resource (mi->dpy, key, "CameraColor"); - if (!XParseColor (mi->dpy, mi->xgwa.colormap, string, &xcolor)) - { - fprintf (stderr, "%s: unparsable color in %s: %s\n", progname, - key, string); - exit (1); - } - free (string); - - color[0] = xcolor.red / 65536.0; - color[1] = xcolor.green / 65536.0; - color[2] = xcolor.blue / 65536.0; - color[3] = 1; -} - - -ENTRYPOINT void -init_camera (ModeInfo *mi) -{ - camera_configuration *bp; - int wire = MI_IS_WIREFRAME(mi); - int i; - MI_INIT (mi, bps); - - bp = &bps[MI_SCREEN(mi)]; - - bp->glx_context = init_GL(mi); - - reshape_camera (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); - - glShadeModel(GL_SMOOTH); - - glEnable(GL_DEPTH_TEST); - glEnable(GL_NORMALIZE); - glEnable(GL_CULL_FACE); - - if (!wire) - { - GLfloat pos[4] = {0.4, 0.2, 0.4, 0.0}; - GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0}; - GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; - GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0}; - - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - - glLightfv(GL_LIGHT0, GL_POSITION, pos); - glLightfv(GL_LIGHT0, GL_AMBIENT, amb); - glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); - glLightfv(GL_LIGHT0, GL_SPECULAR, spc); - } - - bp->user_trackball = gltrackball_init (False); - - bp->dlists = (GLuint *) calloc (countof(all_objs)+1, sizeof(GLuint)); - for (i = 0; i < countof(all_objs); i++) - bp->dlists[i] = glGenLists (1); - - for (i = 0; i < countof(all_objs); i++) - { - const struct gllist *gll = *all_objs[i]; - char *key = 0; - GLfloat spec1[4] = {1.00, 1.00, 1.00, 1.0}; - GLfloat spec2[4] = {0.40, 0.40, 0.70, 1.0}; - GLfloat *spec = spec1; - GLfloat shiny = 20; - - glNewList (bp->dlists[i], GL_COMPILE); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - - glRotatef (-90, 1, 0, 0); - glRotatef (180, 0, 0, 1); - glScalef (6, 6, 6); - - glBindTexture (GL_TEXTURE_2D, 0); - - switch (i) { - case CAMERA_BODY: key = "bodyColor"; break; - case CAMERA_CAP: key = "capColor"; break; - case CAMERA_HINGE: key = "hingeColor"; break; - case CAMERA_MOUNT: key = "mountColor"; break; - case CAMERA_LENS: key = "lensColor"; spec = spec2; break; - case GROUND: key = "groundColor"; spec = spec2; shiny = 128; break; - default: abort(); break; - } - - parse_color (mi, key, bp->component_colors[i]); - - glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); - glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); - - switch (i) { - case GROUND: - if (! ground) - ground = (struct gllist *) calloc (1, sizeof(*ground)); - ground->points = draw_ground (mi, bp->component_colors[i]); - break; - default: - renderList (gll, wire); - /* glColor3f (1, 1, 1); renderListNormals (gll, 100, True); */ - /* glColor3f (1, 1, 0); renderListNormals (gll, 100, False); */ - break; - } - - glMatrixMode(GL_TEXTURE); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - glEndList (); - } - - bp->ncameras = MI_COUNT(mi); - if (bp->ncameras <= 0) bp->ncameras = 1; - bp->cameras = (camera *) calloc (bp->ncameras, sizeof (camera)); - - { - GLfloat range = (MI_COUNT(mi) <= 2) ? 4 : 5.5; - GLfloat extent; - GLfloat spacing = range / bp->ncameras; - if (spacing < 0.7) spacing = 0.7; - extent = spacing * (bp->ncameras - 1); - for (i = 0; i < bp->ncameras; i++) - { - camera *c = &bp->cameras[i]; - c->state = IDLE; - c->pos.x = i*spacing - extent/2; - c->pos.z += 0.7; - if (spacing < 1.6) - c->pos.z = (i & 1 ? 1.1 : -0.3); - c->focus.x = c->pos.x; - c->focus.y = c->pos.y + 1; - c->focus.z = c->pos.z + BEAM_ZOFF; - c->pitch = -50; - } - } - - -# ifdef DEBUG - if (!debug_p) -# endif - /* Let's tilt the floor a little. */ - gltrackball_reset (bp->user_trackball, - -0.70 + frand(1.58), - -0.30 + frand(0.40)); -} - - -static XYZ -normalize (XYZ p) -{ - GLfloat d = sqrt(p.x*p.x + p.y*p.y * p.z*p.z); - if (d < 0.0000001) - p.x = p.y = p.z = 0; - else - { - p.x /= d; - p.y /= d; - p.z /= d; - } - - return p; -} - - -static GLfloat -vector_angle (XYZ a, XYZ b) -{ - double La = sqrt (a.x*a.x + a.y*a.y + a.z*a.z); - double Lb = sqrt (b.x*b.x + b.y*b.y + b.z*b.z); - double cc, angle; - - if (La == 0 || Lb == 0) return 0; - if (a.x == b.x && a.y == b.y && a.z == b.z) return 0; - - /* dot product of two vectors is defined as: - La * Lb * cos(angle between vectors) - and is also defined as: - ax*bx + ay*by + az*bz - so: - La * Lb * cos(angle) = ax*bx + ay*by + az*bz - cos(angle) = (ax*bx + ay*by + az*bz) / (La * Lb) - angle = acos ((ax*bx + ay*by + az*bz) / (La * Lb)); - */ - cc = (a.x*b.x + a.y*b.y + a.z*b.z) / (La * Lb); - if (cc > 1) cc = 1; /* avoid fp rounding error (1.000001 => sqrt error) */ - angle = acos (cc); - - return (angle); -} - - -static int -draw_component (ModeInfo *mi, int i, GLfloat color[4]) -{ - camera_configuration *bp = &bps[MI_SCREEN(mi)]; - if (! color) - color = bp->component_colors[i]; - glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); - glCallList (bp->dlists[i]); - return (*all_objs[i])->points / 3; -} - - -static int -draw_double_component (ModeInfo *mi, int i) -{ - int count = draw_component (mi, i, 0); - - glFrontFace(GL_CCW); - glScalef (1, 1, -1); - count += draw_component (mi, i, 0); - glScalef (1, 1, -1); - glFrontFace(GL_CW); - return count; -} - - -static int -draw_ray (ModeInfo *mi, camera *c) -{ - int wire = MI_IS_WIREFRAME(mi); - int count = 0; - GLfloat length = 10000; - GLfloat thickness = 0.08; - int i; - - glPushMatrix(); - glTranslatef (c->pos.x, c->pos.y, c->pos.z + BEAM_ZOFF); - glRotatef (-c->facing, 0, 0, 1); - glRotatef ( c->pitch, 1, 0, 0); - glRotatef (frand(90), 0, 1, 0); - glScalef (thickness, length, thickness); - glDisable (GL_LIGHTING); - - for (i = 0; i < 5; i++) - { - glColor4f (1, 0, 0, 0.1 + (i * 0.18)); - glBegin (wire ? GL_LINE_LOOP : GL_QUADS); - glVertex3f (0, 0, -0.5); glVertex3f (0, 0, 0.5); - glVertex3f (0, 1, 0.5); glVertex3f (0, 1, -0.5); - glEnd(); - count++; - glBegin (wire ? GL_LINE_LOOP : GL_QUADS); - glVertex3f (-0.5, 0, 0); glVertex3f ( 0.5, 0, 0); - glVertex3f ( 0.5, 1, 0); glVertex3f (-0.5, 1, 0); - glEnd(); - count++; - glBegin (wire ? GL_LINE_LOOP : GL_QUADS); - glVertex3f (0, 1, -0.5); glVertex3f (0, 1, 0.5); - glVertex3f (0, 0, 0.5); glVertex3f (0, 0, -0.5); - glEnd(); - count++; - glBegin (wire ? GL_LINE_LOOP : GL_QUADS); - glVertex3f (-0.5, 1, 0); glVertex3f ( 0.5, 1, 0); - glVertex3f ( 0.5, 0, 0); glVertex3f (-0.5, 0, 0); - glEnd(); - count++; - glScalef (0.7, 1, 0.7); - } - if (!MI_IS_WIREFRAME(mi)) - glEnable (GL_LIGHTING); - glPopMatrix(); - return count; -} - - -static int -draw_camera_1 (ModeInfo *mi, camera *c) -{ - int count = 0; - GLfloat scale = 0.01; - GLfloat color[4] = { 1, 0, 0, 1 }; - glPushMatrix(); - - glTranslatef (c->pos.x, c->pos.y, c->pos.z); - glScalef (scale, scale, scale); - - glRotatef (90, 1, 0, 0); - glRotatef (-90, 0, 1, 0); - - count += draw_double_component (mi, CAMERA_MOUNT); - - glRotatef (-c->facing, 0, 1, 0); - glRotatef (-c->pitch, 0, 0, 1); - - count += draw_double_component (mi, CAMERA_HINGE); - - if (c->state == WARM_UP) - { - if (c->tick < 0.2) - glTranslatef ((0.2 - c->tick) / (scale * 3), 0, 0); - } - - if (c->state == ZOT) - { - glTranslatef ((0.005 - frand(0.01)) / scale, - (0.005 - frand(0.01)) / scale, - (0.005 - frand(0.01)) / scale); - } - - count += draw_double_component (mi, CAMERA_BODY); - - if (c->state == ZOT) - { - glTranslatef ((0.005 - frand(0.01)) / scale, - (0.005 - frand(0.01)) / scale, - (0.005 - frand(0.01)) / scale); - } - - count += draw_double_component (mi, CAMERA_CAP); - - switch (c->state) { - case IDLE: break; - case WARM_UP: color[0] = 1.0 - c->tick; break; - case ZOT: color[0] = 1.0; break; - case COOL_DOWN: color[0] = c->tick; break; - default: abort(); break; - } - - count += draw_component (mi, CAMERA_LENS, - (c->state == IDLE ? 0 : color)); - -# ifdef DEBUG - if (debug_p && c->state != ZOT) - { - glDisable (GL_LIGHTING); - glColor3f (1, 1, 0); - glBegin (GL_LINES); - glVertex3f (0, BEAM_ZOFF / scale, 0); - glVertex3f (-100 / scale, BEAM_ZOFF / scale, 0); - glEnd(); - if (!MI_IS_WIREFRAME(mi)) - glEnable (GL_LIGHTING); - } -# endif - - glPopMatrix(); - - return count; -} - - -/* The position this pedestrian would appear at during the given ratio - through its life cycle. - */ -static XYZ -pedestrian_position (pedestrian *p, GLfloat ratio) -{ - XYZ pos = p->pos; - if (p->speed < 0) - ratio = 1-ratio; - pos.x += p->length * ratio; - pos.z += sin (M_PI * ratio * p->frequency * 2) * p->amplitude - + p->amplitude/2; - return pos; -} - - -static int -draw_pedestrian (ModeInfo *mi, pedestrian *p) -{ - int count = 0; -# ifdef DEBUG - if (debug_p) - { - GLfloat r; - GLfloat step = 0.001; - glDisable (GL_LIGHTING); - glColor3f (0, 0, 1); - - glBegin (GL_LINE_STRIP); - glVertex3f (p->pos.x, p->pos.y, p->pos.z + p->amplitude); - glVertex3f (p->pos.x, p->pos.y, 0); - glVertex3f (p->pos.x + p->length, p->pos.y, 0); - glVertex3f (p->pos.x + p->length, p->pos.y, p->pos.z + p->amplitude); - glEnd(); - - glBegin (GL_LINE_STRIP); - for (r = 0; r <= 1; r += step) - { - XYZ pos = pedestrian_position (p, r); - glVertex3f (pos.x, pos.y, pos.z); - count++; - if (p->ratio >= r && p->ratio < r + step) - { - glVertex3f (pos.x, pos.y, pos.z - p->amplitude); - glVertex3f (pos.x, pos.y, pos.z + p->amplitude); - glVertex3f (pos.x, pos.y, pos.z); - count++; - } - } - glEnd(); - if (!MI_IS_WIREFRAME(mi)) - glEnable (GL_LIGHTING); - } -# endif - return count; -} - - -/* Start someone walking through the scene. - */ -static void -add_pedestrian (ModeInfo *mi) -{ - camera_configuration *bp = &bps[MI_SCREEN(mi)]; - pedestrian *p = (pedestrian *) calloc (1, sizeof(*p)); - static int id = 100; - p->id = id++; - p->length = 35; - p->ratio = 0; - p->pos.x = -p->length/2; - p->pos.y = 3 + frand(10); - p->pos.z = -1.5 + frand(4) + ((random() % 10) ? 0 : frand(8)); - p->frequency = 4 + frand(4); - p->amplitude = 0.1 + ((random() % 10) ? BELLRAND(0.45) : BELLRAND(1.5)); - p->ratio = 0; - p->speed = ((4 + frand(4) + ((random() % 10) ? 0 : frand(10))) - * (random() & 1 ? 1 : -1) - * speed_arg); - - if (bp->pedestrians) - { - pedestrian *p2; /* add it to the end */ - for (p2 = bp->pedestrians; p2->next; p2 = p2->next) - ; - p2->next = p; - } - else - { - p->next = bp->pedestrians; - bp->pedestrians = p; - } -} - - -static void -free_pedestrian (ModeInfo *mi, pedestrian *p) -{ - camera_configuration *bp = &bps[MI_SCREEN(mi)]; - Bool ok = False; - if (!p) abort(); - if (p == bp->pedestrians) - { - bp->pedestrians = p->next; - ok = True; - } - else - { - pedestrian *p0; - for (p0 = bp->pedestrians; p0; p0 = p0->next) - if (p0->next == p) - { - p0->next = p0->next ? p0->next->next : 0; - ok = True; - break; - } - } - if (!ok) abort(); - p->next = 0; - free (p); -} - - -static void -tick_pedestrian (ModeInfo *mi, pedestrian *p) -{ - p->ratio += 0.001 * (p->speed > 0 ? p->speed : -p->speed); - if (p->ratio >= 1) - free_pedestrian (mi, p); -} - - -/* Extract the position of the thing this camera would like to look at. - */ -static void -set_camera_focus (ModeInfo *mi, camera *c) -{ - camera_configuration *bp = &bps[MI_SCREEN(mi)]; - - if (c->focus_id > 0) /* Look at pedestrian with id N */ - { - long id = c->focus_id; - pedestrian *p; - for (p = bp->pedestrians; p; p = p->next) - if (p->id == id) - break; - if (p) - c->focus = pedestrian_position (p, p->ratio); - else - c->focus_id = 0; /* that pedestrian has escaped */ - } - else if (c->focus_id < 0) /* Look at camera -N-1 */ - { - long n = -c->focus_id - 1; - if (bp->ncameras > n) - c->focus = bp->cameras[n].pos; - } -} - - -static void -tick_camera (ModeInfo *mi, camera *c) -{ - camera_configuration *bp = &bps[MI_SCREEN(mi)]; - - GLfloat X, Y, Z; - set_camera_focus (mi, c); - - X = c->focus.x - c->pos.x; - Y = c->focus.y - c->pos.y; - Z = c->focus.z - c->pos.z - BEAM_ZOFF; - - if (X != 0 || Y != 0) - { - GLfloat ofacing = c->facing; - GLfloat opitch = c->pitch; - - GLfloat target_facing = atan2 (X, Y) * (180 / M_PI); - GLfloat target_pitch = atan2 (Z, sqrt(X*X + Y*Y)) * (180 / M_PI); - - /* Adjust the current velocity. - If we are nearing the target, slow down (but don't stop). - Otherwise, speed up (but don't break the speed limit). - */ - { - GLfloat accel = 0.5 * speed_arg; - GLfloat decel_range = 20; - GLfloat max_velocity = 5 * speed_arg; - GLfloat close_enough = 0.5 * speed_arg; - - GLfloat dx = target_facing - c->facing; - GLfloat dy = target_pitch - c->pitch; - GLfloat angular_distance = sqrt (dx*dx + dy*dy); - - /* Split the velocity into vx and vy components. This isn't - quite right since this treats them as Cartesian rather than - polar, but it's close enough. - */ - GLfloat r = (dx == 0) ? 1 : ABS(dy) / ABS(dx); - GLfloat vx = 1-r; - GLfloat vy = r; - - if (angular_distance < decel_range) /* Nearing target, slow down */ - { - c->velocity -= accel; - if (c->velocity <= 0) - c->velocity = accel; - } - else - { - c->velocity += accel; - if (c->velocity > max_velocity) - c->velocity = max_velocity; - } - - /* Don't overshoot */ - if (vx > ABS(dx)) vx = ABS(dx); - if (vy > ABS(dy)) vy = ABS(dy); - - - /* Rotate toward target by current angular velocity. */ - c->facing += vx * c->velocity * (target_facing > c->facing ? 1 : -1); - c->pitch += vy * c->velocity * (target_pitch > c->pitch ? 1 : -1); - - /* If we are pointed *really close* to the target, just lock on, - to avoid twitchy overshoot rounding errors. - */ - if (angular_distance < close_enough) - { - c->facing = target_facing; - c->pitch = target_pitch; - } - - /* Constrain to hinge's range of motion */ - c->facing = MAX (-90, MIN (90, c->facing)); - c->pitch = MAX (-90, MIN (55, c->pitch)); - - /* After this motion, our prevailing velocity (for next time) - is the angular distance we actually moved. - */ - dx = c->facing - ofacing; - dy = c->pitch - opitch; - c->velocity = sqrt (dx*dx + dy*dy); - } - } - -# ifdef DEBUG - if (debug_p && 1) - /* Mark the point on which this camera is focusing. */ - { - glPushMatrix(); - glDisable (GL_LIGHTING); - glColor3f(0.3, 0.3, 0.3); - glBegin (GL_LINES); - glVertex3f (c->pos.x, c->pos.y, c->pos.z + BEAM_ZOFF); - glVertex3f (c->focus.x, c->focus.y, c->focus.z); - glEnd(); - glColor3f(1,1,1); - glBegin (GL_LINES); - glVertex3f (c->focus.x-0.25, c->focus.y, c->focus.z); - glVertex3f (c->focus.x+0.25, c->focus.y, c->focus.z); - glVertex3f (c->focus.x, c->focus.y-0.25, c->focus.z); - glVertex3f (c->focus.x, c->focus.y+0.25, c->focus.z); - glVertex3f (c->focus.x, c->focus.y, c->focus.z-0.25); - glVertex3f (c->focus.x, c->focus.y, c->focus.z+0.25); - glEnd(); - if (!MI_IS_WIREFRAME(mi)) - glEnable (GL_LIGHTING); - glPopMatrix(); - } -# endif - - /* If this camera is looking at another camera, get shy and look away - if the target sees us looking. - */ - if (c->focus_id < 0) - { - camera *c2 = &bp->cameras[-1 - c->focus_id]; - XYZ a, b; - GLfloat aa = c->facing / (180 / M_PI); - GLfloat bb = c->pitch / (180 / M_PI); - GLfloat angle; - - a.y = cos(aa)* cos(bb); - a.x = sin(aa)* cos(bb); - a.z = sin(bb); - - aa = c2->facing / (180 / M_PI); - bb = c2->pitch / (180 / M_PI); - b.y = cos(aa)* cos(bb); - b.x = sin(aa)* cos(bb); - b.z = sin(bb); - - angle = vector_angle (normalize(a), normalize(b)) * (180 / M_PI); - - if (angle > 100) - { - c->focus_id = 0; - /* Look "away" which means in the same direction. */ - c->focus.x = c->pos.x + (c2->focus.x - c2->pos.x); - c->focus.y = c->pos.y + (c2->focus.y - c2->pos.y); - c->focus.z = c->pos.z + (c2->focus.z - c2->pos.z); - /* Look at either the sky or the ground.*/ - c->focus.z = c->focus.x * (random() & 1 ? 1 : -1) * 5; - c->velocity = c2->velocity * 3; - } - } - - - /* Randomly pick some other things to look at. - */ - - if (c->state == IDLE && - (c->focus_id <= 0 - ? !(random() % (int) MAX (1, (50 / speed_arg))) - : !(random() % (int) MAX (1, (1000 / speed_arg))))) - { - - /* Shiny! Start paying attention to something else. */ - - if ((bp->ncameras > 1 && !(random() % 20))) /* look at a camera */ - { - int which = random() % 4; - long i; - for (i = 0; i < bp->ncameras; i++) - if (c == &bp->cameras[i]) - break; - - /* Look at cameras 1 or 2 away in each direction, but not farther. - Since we arrange them in 2 staggered lines, those are the only - four that are in line of sight. - */ - if (i >= 2 && which == 0) - which = i-2; - else if (i >= 1 && which == 1) - which = i-1; - else if (i < bp->ncameras-2 && which == 2) - which = i+2; - else if (i == bp->ncameras-1) - which = i-1; - else /* (i < bp->ncameras-2 && which == 3) */ - which = i+1; - - c->focus_id = -1 - which; - } - else /* look at a pedestrian */ - { - int n = 0; - pedestrian *p; - for (p = bp->pedestrians; p; p = p->next) - n++; - if (n > 0) - { - n = random() % n; - p = bp->pedestrians; - while (n > 0 && p) - p = p->next; - if (p) - c->focus_id = p->id; - } - } - } - - /* Run the animation */ - - if (c->state != IDLE) - { - pedestrian *p = bp->pedestrians; /* first one */ - if (p) c->focus_id = p->id; - - switch (c->state) { - case WARM_UP: c->tick -= 0.01 * speed_arg; break; - case ZOT: c->tick -= 0.006 * speed_arg; - if (p) p->speed *= 0.995; /* target takes 1d6 HP damage */ - break; - case COOL_DOWN: c->tick -= 0.02 * speed_arg; break; - default: abort(); break; - } - - if (c->tick <= 0) - { - c->tick = 1.0; - switch (c->state) { - case WARM_UP: c->state = ZOT; break; - case ZOT: c->state = COOL_DOWN; - c->focus_id = 0; - if (p) p->ratio = 1.0; /* threat eliminated */ - break; - case COOL_DOWN: c->state = IDLE; break; - default: abort(); break; - } - } - } - - if (bp->cameras[0].state == IDLE && - bp->pedestrians && - bp->pedestrians[0].ratio < 0.3 && - !(random() % MAX (1, (int) (50000 / speed_arg)))) - { - /* CASE NIGHTMARE RED detected, engage SCORPION STARE by authority - of MAGINOT BLUE STARS. */ - int i; - for (i = 0; i < bp->ncameras; i++) - { - bp->cameras[i].state = WARM_UP; - bp->cameras[i].tick = 1.0; - } - } -} - - -static int -draw_ground (ModeInfo *mi, GLfloat color[4]) -{ - int wire = MI_IS_WIREFRAME(mi); - GLfloat i, j, k, h; - - /* When using fog, iOS apparently doesn't like lines or quads that are - really long, and extend very far outside of the scene. Maybe? If the - length of the line (cells * cell_size) is greater than 25 or so, lines - that are oriented steeply away from the viewer tend to disappear - (whether implemented as GL_LINES or as GL_QUADS). - - So we do a bunch of smaller grids instead of one big one. - */ - int cells = 20; - GLfloat cell_size = 0.4; - int points = 0; - int gridsw = 10; - int gridsh = 2; - - glPushMatrix(); - - if (!wire) - { - GLfloat fog_color[4] = { 0, 0, 0, 1 }; - - glLineWidth (2); - glEnable (GL_LINE_SMOOTH); - glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - - glFogi (GL_FOG_MODE, GL_EXP2); - glFogfv (GL_FOG_COLOR, fog_color); - glFogf (GL_FOG_DENSITY, 0.017); - glFogf (GL_FOG_START, -cells/2 * cell_size * gridsh); - glEnable (GL_FOG); - } - - glColor4fv (color); - glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); - - glTranslatef (-cells * gridsw * cell_size / 2, 0, 0); - for (h = 0; h < 2; h++) - { - glPushMatrix(); - glTranslatef (0, cells * cell_size / 2, 0); - for (j = 0; j < gridsh; j++) - { - glPushMatrix(); - for (k = 0; k < gridsw; k++) - { - glBegin (GL_LINES); - for (i = -cells/2; i < cells/2; i++) - { - GLfloat a = i * cell_size; - GLfloat b = cells/2 * cell_size; - glVertex3f (a, -b, 0); glVertex3f (a, b, 0); points++; - glVertex3f (-b, a, 0); glVertex3f (b, a, 0); points++; - } - glEnd(); - glTranslatef (cells * cell_size, 0, 0); - } - glPopMatrix(); - glTranslatef (0, cells * cell_size, 0); - } - glPopMatrix(); - glRotatef (90, 1, 0, 0); - } - - if (!wire) - glDisable (GL_LINE_SMOOTH); - - glPopMatrix(); - - return points; -} - - -ENTRYPOINT void -draw_camera (ModeInfo *mi) -{ - camera_configuration *bp = &bps[MI_SCREEN(mi)]; - Display *dpy = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - GLfloat camera_size; - int i; - - if (!bp->glx_context) - return; - - glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glPushMatrix (); - - glRotatef (current_device_rotation(), 0, 0, 1); /* right side up */ - gltrackball_rotate (bp->user_trackball); - -# ifdef HAVE_MOBILE - { - GLfloat s = 0.6; - glScalef (s, s, s); - } -# endif - -# ifdef DEBUG - if (debug_p) - { - GLfloat s = 0.2; - glScalef (s, s, s); - glRotatef (30, 0, 1, 0); - glRotatef (15, 1, 0, 0); - glTranslatef (0, 0, -80); - } -# endif - - mi->polygon_count = 0; - - camera_size = 5; - - if (MI_COUNT(mi) <= 2) /* re-frame the scene a little bit */ - glTranslatef (0, -1, 7); - if (MI_COUNT(mi) >= 20) - glTranslatef (0, -1.5, -5); - if (MI_COUNT(mi) >= 40) - glTranslatef (0, 2, -15); - - glScalef (camera_size, camera_size, camera_size); - - /* +Z is toward sky; +X is toward the right along the back wall; - +Y is toward the viewer. */ - glRotatef (-90, 1, 0, 0); - glScalef (1, -1, 1); - - glPushMatrix(); - glScalef (1/camera_size, 1/camera_size, 1/camera_size); - glTranslatef (0, -2.38, -8); /* Move the ground down and back */ - glCallList (bp->dlists[GROUND]); - mi->polygon_count += ground->points; - - glPopMatrix(); - - { - pedestrian *p, *p2; - for (p = bp->pedestrians, p2 = p ? p->next : 0; - p; - p = p2, p2 = p2 ? p2->next : 0) - { - mi->polygon_count += draw_pedestrian (mi, p); - tick_pedestrian (mi, p); /* might free p */ - } - - if (!bp->pedestrians || !(random() % MAX (1, (int) (200 / speed_arg)))) - add_pedestrian (mi); - } - - for (i = 0; i < bp->ncameras; i++) - { - camera *c = &bp->cameras[i]; - mi->polygon_count += draw_camera_1 (mi, c); - tick_camera (mi, c); - } - - for (i = 0; i < bp->ncameras; i++) - { - camera *c = &bp->cameras[i]; - if (c->state == ZOT) /* Do this last, for alpha blending */ - mi->polygon_count += draw_ray (mi, c); - } - - glPopMatrix (); - - if (mi->fps_p) do_fps (mi); - glFinish(); - - glXSwapBuffers(dpy, window); -} - - -ENTRYPOINT void -free_camera (ModeInfo *mi) -{ - camera_configuration *bp = &bps[MI_SCREEN(mi)]; - pedestrian *p; - int i; - - if (!bp->glx_context) return; - glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context); - - if (bp->user_trackball) gltrackball_free (bp->user_trackball); - if (bp->cameras) free (bp->cameras); - p = bp->pedestrians; - while (p) { - pedestrian *p2 = p->next; - free (p); - p = p2; - } - if (bp->dlists) { - for (i = 0; i < countof(all_objs); i++) - if (glIsList(bp->dlists[i])) glDeleteLists(bp->dlists[i], 1); - free (bp->dlists); - } -} - -XSCREENSAVER_MODULE_2 ("Vigilance", vigilance, camera) - -#endif /* USE_GL */ |
