summaryrefslogtreecommitdiffstats
path: root/hacks/glx/vigilance.c
diff options
context:
space:
mode:
Diffstat (limited to 'hacks/glx/vigilance.c')
-rw-r--r--hacks/glx/vigilance.c1170
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 */