summaryrefslogtreecommitdiffstats
path: root/hacks/glx/skytentacles.c
diff options
context:
space:
mode:
authorSimon Rettberg2024-09-06 14:42:37 +0200
committerSimon Rettberg2024-09-06 14:42:37 +0200
commitbadef32037f52f79abc1f1440b786cd71afdf270 (patch)
tree412b792d4cab4a7a110db82fcf74fe8a1ac55ec1 /hacks/glx/skytentacles.c
parentDelete pre-6.00 files (diff)
downloadxscreensaver-master.tar.gz
xscreensaver-master.tar.xz
xscreensaver-master.zip
Diffstat (limited to 'hacks/glx/skytentacles.c')
-rw-r--r--hacks/glx/skytentacles.c1123
1 files changed, 0 insertions, 1123 deletions
diff --git a/hacks/glx/skytentacles.c b/hacks/glx/skytentacles.c
deleted file mode 100644
index 34057df..0000000
--- a/hacks/glx/skytentacles.c
+++ /dev/null
@@ -1,1123 +0,0 @@
-/* Sky Tentacles, Copyright (c) 2008-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.
- */
-
-#define DEFAULTS "*delay: 30000 \n" \
- "*count: 9 \n" \
- "*showFPS: False \n" \
- "*wireframe: False \n" \
-
-# define release_tentacles 0
-
-#include "xlockmore.h"
-#include "colors.h"
-#include "normals.h"
-#include "rotator.h"
-#include "gltrackball.h"
-#include <ctype.h>
-
-#include "ximage-loader.h"
-#include "images/gen/scales_png.h"
-
-#ifdef USE_GL /* whole file */
-
-# ifndef HAVE_JWZGLES
-# define HAVE_POLYGONMODE
-# endif
-
-#define DEF_SPEED "1.0"
-#define DEF_SMOOTH "True"
-#define DEF_TEXTURE "True"
-#define DEF_CEL "False"
-#define DEF_INTERSECT "False"
-#define DEF_SLICES "16"
-#define DEF_SEGMENTS "24"
-#define DEF_WIGGLINESS "0.35"
-#define DEF_FLEXIBILITY "0.35"
-#define DEF_THICKNESS "1.0"
-#define DEF_LENGTH "9.0"
-#define DEF_COLOR "#305A30"
-#define DEF_STRIPE "#451A30"
-#define DEF_SUCKER "#453E30"
-#define DEF_DEBUG "False"
-
-#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
-
-typedef struct {
- GLfloat length; /* length of the segment coming out of this segment */
- GLfloat th; /* vector tilt (on yz plane) from previous segment */
- GLfloat phi; /* vector rotation (on xy plane) from previous segment */
- GLfloat thickness; /* radius of tentacle at the bottom of this segment */
- rotator *rot; /* motion modeller */
-} segment;
-
-typedef struct {
- ModeInfo *mi;
- GLfloat x, y, z; /* position of the base */
- int nsegments;
- segment *segments;
- GLfloat tentacle_color[4], stripe_color[4], sucker_color[4];
-} tentacle;
-
-typedef struct {
- GLXContext *glx_context;
- trackball_state *trackball;
- Bool button_down_p;
-
- int ntentacles;
- int tentacles_size;
- tentacle **tentacles;
- GLfloat tentacle_color[4], stripe_color[4], sucker_color[4];
-
- int torus_polys;
- int torus_step;
- XYZ *torus_points;
- XYZ *torus_normals;
-
- GLfloat line_thickness;
- GLfloat outline_color[4];
- XImage *texture;
- GLuint texid;
-
- Bool left_p;
-
-} tentacles_configuration;
-
-static tentacles_configuration *tcs = NULL;
-
-static int debug_p;
-static GLfloat arg_speed;
-static int smooth_p;
-static int texture_p;
-static int cel_p;
-static int intersect_p;
-static int arg_slices;
-static int arg_segments;
-static GLfloat arg_thickness;
-static GLfloat arg_length;
-static GLfloat arg_wiggliness;
-static GLfloat arg_flexibility;
-static char *arg_color, *arg_stripe, *arg_sucker;
-
-/* we can only have one light when doing cel shading */
-static GLfloat light_pos[4] = {1.0, 1.0, 1.0, 0.0};
-
-
-static XrmOptionDescRec opts[] = {
- { "-speed", ".speed", XrmoptionSepArg, 0 },
- { "-no-smooth", ".smooth", XrmoptionNoArg, "False" },
- { "-texture", ".texture", XrmoptionNoArg, "True" },
- { "-no-texture", ".texture", XrmoptionNoArg, "False" },
- { "-cel", ".cel", XrmoptionNoArg, "True" },
- { "-no-cel", ".cel", XrmoptionNoArg, "False" },
- { "-intersect", ".intersect", XrmoptionNoArg, "True" },
- { "-no-intersect", ".intersect", XrmoptionNoArg, "False" },
- { "-slices", ".slices", XrmoptionSepArg, 0 },
- { "-segments", ".segments", XrmoptionSepArg, 0 },
- { "-thickness", ".thickness", XrmoptionSepArg, 0 },
- { "-length", ".length", XrmoptionSepArg, 0 },
- { "-wiggliness", ".wiggliness", XrmoptionSepArg, 0 },
- { "-flexibility", ".flexibility", XrmoptionSepArg, 0 },
- { "-color", ".tentacleColor", XrmoptionSepArg, 0 },
- { "-stripe-color", ".stripeColor", XrmoptionSepArg, 0 },
- { "-sucker-color", ".suckerColor", XrmoptionSepArg, 0 },
- { "-debug", ".debug", XrmoptionNoArg, "True" },
-};
-
-static argtype vars[] = {
- {&arg_speed, "speed", "Speed", DEF_SPEED, t_Float},
- {&smooth_p, "smooth", "Smooth", DEF_SMOOTH, t_Bool},
- {&texture_p, "texture", "Texture", DEF_TEXTURE, t_Bool},
- {&cel_p, "cel", "Cel", DEF_CEL, t_Bool},
- {&intersect_p, "intersect", "Intersect", DEF_INTERSECT, t_Bool},
- {&arg_slices, "slices", "Slices", DEF_SLICES, t_Int},
- {&arg_segments, "segments", "Segments", DEF_SEGMENTS, t_Int},
- {&arg_thickness, "thickness", "Thickness", DEF_THICKNESS, t_Float},
- {&arg_length, "length", "Length", DEF_LENGTH, t_Float},
- {&arg_wiggliness, "wiggliness", "Wiggliness", DEF_WIGGLINESS, t_Float},
- {&arg_flexibility, "flexibility", "Flexibility", DEF_FLEXIBILITY, t_Float},
- {&arg_color, "tentacleColor", "Color", DEF_COLOR, t_String},
- {&arg_stripe, "stripeColor", "Color", DEF_STRIPE, t_String},
- {&arg_sucker, "suckerColor", "Color", DEF_SUCKER, t_String},
- {&debug_p, "debug", "Debug", DEF_DEBUG, t_Bool},
-};
-
-ENTRYPOINT ModeSpecOpt tentacles_opts = {countof(opts), opts, countof(vars), vars, NULL};
-
-
-/* Window management, etc
- */
-ENTRYPOINT void
-reshape_tentacles (ModeInfo *mi, int width, int height)
-{
- tentacles_configuration *tc = &tcs[MI_SCREEN(mi)];
- 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, (GLint) width, (GLint) height);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective (30.0, 1/h, 1.0, 100.0);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- gluLookAt( 0.0, 0.0, 30.0,
- 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0);
-
- glClear(GL_COLOR_BUFFER_BIT);
-
- tc->line_thickness = (MI_IS_WIREFRAME (mi) ? 1 : MAX (3, width / 200));
-}
-
-
-static void
-normalize (GLfloat *x, GLfloat *y, GLfloat *z)
-{
- GLfloat d = sqrt((*x)*(*x) + (*y)*(*y) + (*z)*(*z));
- *x /= d;
- *y /= d;
- *z /= d;
-}
-
-static GLfloat
-dot (GLfloat x0, GLfloat y0, GLfloat z0,
- GLfloat x1, GLfloat y1, GLfloat z1)
-{
- return x0*x1 + y0*y1 + z0*z1;
-}
-
-
-static void
-compute_unit_torus (ModeInfo *mi, double ratio, int slices1, int slices2)
-{
- tentacles_configuration *tc = &tcs[MI_SCREEN(mi)];
- Bool wire = MI_IS_WIREFRAME (mi);
- int i, j, k, fp;
-
- if (wire) slices1 /= 2;
- if (wire) slices2 /= 4;
- if (slices1 < 3) slices1 = 3;
- if (slices2 < 3) slices2 = 3;
-
- tc->torus_polys = slices1 * (slices2+1) * 2;
- tc->torus_points = (XYZ *) calloc (tc->torus_polys + 1,
- sizeof (*tc->torus_points));
- tc->torus_normals = (XYZ *) calloc (tc->torus_polys + 1,
- sizeof (*tc->torus_normals));
- tc->torus_step = 2 * (slices2+1);
- fp = 0;
- for (i = 0; i < slices1; i++)
- for (j = 0; j <= slices2; j++)
- for (k = 0; k <= 1; k++)
- {
- double s = (i + k) % slices1 + 0.5;
- double t = j % slices2;
- XYZ p;
- p.x = cos(t*M_PI*2/slices2) * cos(s*M_PI*2/slices1);
- p.y = sin(t*M_PI*2/slices2) * cos(s*M_PI*2/slices1);
- p.z = sin(s*M_PI*2/slices1);
- tc->torus_normals[fp] = p;
-
- p.x = (1 + ratio * cos(s*M_PI*2/slices1)) * cos(t*M_PI*2/slices2) / 2;
- p.y = (1 + ratio * cos(s*M_PI*2/slices1)) * sin(t*M_PI*2/slices2) / 2;
- p.z = ratio * sin(s*M_PI*2/slices1) / 2;
- tc->torus_points[fp] = p;
- fp++;
- }
- if (fp != tc->torus_polys) abort();
- tc->torus_polys = fp;
-}
-
-
-/* Initializes a new tentacle and stores it in the list.
- */
-static tentacle *
-make_tentacle (ModeInfo *mi, int which, int total)
-{
- tentacles_configuration *tc = &tcs[MI_SCREEN(mi)];
- tentacle *t = (tentacle *) calloc (1, sizeof (*t));
- double brightness;
- int i;
-
- t->mi = mi;
-
- /* position tentacles on a grid */
- {
- int cols = (int) (sqrt(total) + 0.5);
- int rows = (total+cols-1) / cols;
- int xx = which % cols;
- int yy = which / cols;
- double spc = arg_thickness * 0.8;
- if (!intersect_p) cols = 1, xx = 0;
- t->x = (cols * spc / 2) - (spc * (xx + 0.5));
- t->y = (rows * spc / 2) - (spc * (yy + 0.5));
- t->z = 0;
- }
-
- /* Brighten or darken the colors of this tentacle from the default.
- */
- brightness = 0.6 + frand(3.0);
- memcpy (t->tentacle_color, tc->tentacle_color, 4 * sizeof(*t->tentacle_color));
- memcpy (t->stripe_color, tc->stripe_color, 4 * sizeof(*t->stripe_color));
- memcpy (t->sucker_color, tc->sucker_color, 4 * sizeof(*t->sucker_color));
-# define FROB(X) \
- t->X[0] *= brightness; if (t->X[0] > 1) t->X[0] = 1; \
- t->X[1] *= brightness; if (t->X[1] > 1) t->X[1] = 1; \
- t->X[2] *= brightness; if (t->X[2] > 1) t->X[2] = 1
- FROB (tentacle_color);
- FROB (stripe_color);
- FROB (sucker_color);
-# undef FROB
-
- t->nsegments = (arg_segments) + BELLRAND(arg_segments);
-
- t->segments = (segment *) calloc (t->nsegments+1, sizeof(*t->segments));
- for (i = 0; i < t->nsegments; i++)
- {
- double spin_speed = 0;
- double spin_accel = 0;
- double wander_speed = arg_speed * (0.02 + BELLRAND(0.1));
- t->segments[i].rot = make_rotator (spin_speed, spin_speed, spin_speed,
- spin_accel, wander_speed, True);
- }
-
- t->segments[0].thickness = (((arg_thickness * 0.5) +
- BELLRAND(arg_thickness * 0.6))
- / 1.0);
-
- if (tc->tentacles_size <= tc->ntentacles)
- {
- tc->tentacles_size = (tc->tentacles_size * 1.2) + tc->ntentacles + 2;
- tc->tentacles = (tentacle **)
- realloc (tc->tentacles, tc->tentacles_size * sizeof(*tc->tentacles));
- if (! tc->tentacles)
- {
- fprintf (stderr, "%s: out of memory (%d tentacles)\n",
- progname, tc->tentacles_size);
- exit (1);
- }
- }
-
- tc->tentacles[tc->ntentacles++] = t;
- return t;
-}
-
-
-static void
-draw_sucker (tentacle *t, Bool front_p)
-{
- tentacles_configuration *tc = &tcs[MI_SCREEN(t->mi)];
- Bool wire = MI_IS_WIREFRAME (t->mi);
- int i, j;
- int strips = tc->torus_polys / tc->torus_step;
- int points = 0;
-
- glFrontFace (front_p ? GL_CW : GL_CCW);
- for (i = 0; i < strips; i++)
- {
- int ii = i * tc->torus_step;
-
- /* Leave off the polygons on the underside. This reduces polygon
- count by about 10% with the default settings. */
- if (strips > 4 && i >= strips/2 && i < strips-1)
- continue;
-
- glBegin (wire ? GL_LINE_STRIP : GL_QUAD_STRIP);
- for (j = 0; j < tc->torus_step; j++)
- {
- XYZ sp = tc->torus_points[ii+j];
- XYZ sn = tc->torus_normals[ii+j];
- glNormal3f(sn.x, sn.y, sn.z);
- glVertex3f(sp.x, sp.y, sp.z);
- points++;
- }
- glEnd();
- }
- t->mi->polygon_count += points/2;
-}
-
-static void
-draw_tentacle_1 (tentacle *t, Bool front_p, Bool outline_p)
-{
- tentacles_configuration *tc = &tcs[MI_SCREEN(t->mi)];
- int i;
- Bool wire = MI_IS_WIREFRAME (t->mi);
- XYZ ctr = { 0,0,0 }; /* current position of base of segment */
- double cth = 0; /* overall orientation of current segment */
- double cphi = 0;
- double cth_cos = 1, cth_sin = 0;
- double cphi_cos = 1, cphi_sin = 0;
-
- GLfloat light[3]; /* vector to the light */
-
- GLfloat t0 = 0.0; /* texture coordinate */
-
- XYZ *ring, *oring; /* points around the edge (this, and previous) */
- XYZ *norm, *onorm; /* their normals */
- XYZ *ucirc; /* unit circle, to save some trig */
-
- /* Which portion of the radius the indented/colored stripe takes up */
- int indented_points = arg_slices * 0.2;
-
- /* We do rotation this way to minimize the number of calls to sin/cos.
- We have to hack the transformations manually instead of using
- glRotate/glTranslate because those calls are not allowed *inside*
- of a glBegin/glEnd block...
- */
-# define ROT(P) do { \
- XYZ _p = P; \
- _p.y = ((P.y * cth_sin - P.x * cth_cos)); \
- _p.x = ((P.y * cth_cos + P.x * cth_sin) * cphi_sin - (P.z * cphi_cos)); \
- _p.z = ((P.y * cth_cos + P.x * cth_sin) * cphi_cos + (P.z * cphi_sin)); \
- P = _p; \
- } while(0)
-
- ring = (XYZ *) malloc (arg_slices * sizeof(*ring));
- norm = (XYZ *) malloc (arg_slices * sizeof(*norm));
- oring = (XYZ *) malloc (arg_slices * sizeof(*oring));
- onorm = (XYZ *) malloc (arg_slices * sizeof(*onorm));
- ucirc = (XYZ *) malloc (arg_slices * sizeof(*ucirc));
-
- light[0] = light_pos[0];
- light[1] = light_pos[1];
- light[2] = light_pos[2];
- normalize (&light[0], &light[1], &light[2]);
-
- for (i = 0; i < arg_slices; i++)
- {
- double a = M_PI * 2 * i / arg_slices;
- ucirc[i].x = cos(a);
- ucirc[i].y = sin(a);
- ucirc[i].z = 0;
- }
-
-
-# ifdef HAVE_POLYGONMODE
- if (cel_p)
- glPolygonMode (GL_FRONT_AND_BACK, (front_p ? GL_FILL : GL_LINE));
-# endif
-
- glPushMatrix();
- glTranslatef (t->x, t->y, t->z);
-
- if (debug_p)
- {
- glPushAttrib (GL_ENABLE_BIT);
- glDisable (GL_LIGHTING);
- glDisable (GL_TEXTURE_1D);
- glDisable (GL_TEXTURE_2D);
- glColor3f (1, 1, 1);
- glLineWidth (1);
- glBegin(GL_LINE_LOOP);
- for (i = 0; i < arg_slices; i++)
- glVertex3f (arg_thickness / 2 * cos (M_PI * 2 * i / arg_slices),
- arg_thickness / 2 * sin (M_PI * 2 * i / arg_slices),
- 0);
- glEnd();
- glPopAttrib();
- }
-
- if (!front_p || outline_p)
- glColor4fv (tc->outline_color);
- else if (wire)
- glColor4fv (t->tentacle_color);
- else
- {
- static const GLfloat bspec[4] = {1.0, 1.0, 1.0, 1.0};
- static const GLfloat bshiny = 128.0;
- glMaterialfv (GL_FRONT, GL_SPECULAR, bspec);
- glMateriali (GL_FRONT, GL_SHININESS, bshiny);
- }
-
- for (i = 0; i < t->nsegments; i++)
- {
- int j;
- GLfloat t1 = t0 + i / (t->nsegments * M_PI * 2);
-
- for (j = 0; j < arg_slices; j++)
- {
- /* Construct a vertical disc at the origin, to use as the
- base of this segment.
- */
- double r = t->segments[i].thickness / 2;
-
- if (j <= indented_points/2 || j >= arg_slices-indented_points/2)
- r *= 0.75; /* indent the stripe */
-
- if (outline_p)
- r *= 1.1;
-
- ring[j].x = r * ucirc[j].x;
- ring[j].y = 0;
- ring[j].z = r * ucirc[j].y;
-
- /* Then rotate the points by the angle of the current segment. */
- ROT(ring[j]);
-
- /* Then move the ring to the base of this segment. */
- ring[j].x += ctr.x;
- ring[j].y += ctr.y;
- ring[j].z += ctr.z;
- }
-
-
- /* Compute the normals of the faces on this segment. We do this
- first so that the normals of the vertexes can be the average
- of the normals of the faces.
- #### Uh, except I didn't actually implement that...
- but it would be a good idea.
- */
- if (i > 0)
- for (j = 0; j <= arg_slices; j++)
- {
- int j0 = j % arg_slices;
- int j1 = (j+1) % arg_slices;
- norm[j0] = calc_normal (oring[j0], ring[j0], ring[j1]);
- }
-
- /* Draw!
- */
- if (i > 0)
- {
- int j;
- glLineWidth (tc->line_thickness);
- glFrontFace (front_p ? GL_CCW : GL_CW);
- glBegin (wire ? GL_LINES : smooth_p ? GL_QUAD_STRIP : GL_QUADS);
- for (j = 0; j <= arg_slices; j++)
- {
- int j0 = j % arg_slices;
- int j1 = (j+1) % arg_slices;
-
- GLfloat ts = j / (double) arg_slices;
-
- if (!front_p || outline_p)
- glColor4fv (tc->outline_color);
- else if (j <= indented_points/2 ||
- j >= arg_slices-indented_points/2)
- {
- glColor4fv (t->stripe_color);
- glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
- t->stripe_color);
- }
- else
- {
- glColor4fv (t->tentacle_color);
- glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
- t->tentacle_color);
- }
-
- /* For cel shading, the 1d texture coordinate (s) is the
- dot product of the lighting vector and the vertex normal.
- */
- if (cel_p)
- {
- t0 = dot (light[0], light[1], light[2],
- onorm[j0].x, onorm[j0].y, onorm[j0].z);
- t1 = dot (light[0], light[1], light[2],
- norm[j0].x, norm[j0].y, norm[j0].z);
- if (t0 < 0) t0 = 0;
- if (t1 < 0) t1 = 0;
- }
-
- glTexCoord2f (t0, ts);
- glNormal3f (onorm[j0].x, onorm[j0].y, onorm[j0].z);
- glVertex3f (oring[j0].x, oring[j0].y, oring[j0].z);
-
- glTexCoord2f (t1, ts);
- glNormal3f ( norm[j0].x, norm[j0].y, norm[j0].z);
- glVertex3f ( ring[j0].x, ring[j0].y, ring[j0].z);
-
- if (!smooth_p)
- {
- ts = j1 / (double) arg_slices;
- glTexCoord2f (t1, ts);
- glVertex3f ( ring[j1].x, ring[j1].y, ring[j1].z);
- glTexCoord2f (t0, ts);
- glVertex3f (oring[j1].x, oring[j1].y, oring[j1].z);
- }
- t->mi->polygon_count++;
- }
- glEnd ();
-
- if (wire)
- {
- glBegin (GL_LINE_LOOP);
- for (j = 0; j < arg_slices; j++)
- glVertex3f (ring[j].x, ring[j].y, ring[j].z);
- glEnd();
- }
-
- /* Now draw the suckers!
- */
- {
- double seg_length = arg_length / t->nsegments;
- double sucker_size = arg_thickness / 5;
- double sucker_spacing = sucker_size * 1.3;
- int nsuckers = seg_length / sucker_spacing;
- double oth = cth - t->segments[i-1].th;
- double ophi = cphi - t->segments[i-1].phi;
- int k;
-
- if (!wire)
- glLineWidth (MAX (2, tc->line_thickness / 2.0));
- glDisable (GL_TEXTURE_2D);
-
- /* Sometimes we have N suckers on one segment;
- sometimes we have one sucker every N segments. */
- if (nsuckers == 0)
- {
- int segs_per_sucker =
- (int) ((sucker_spacing / seg_length) + 0.5);
- nsuckers = (i % segs_per_sucker) ? 0 : 1;
- }
-
- if (outline_p)
- {
- glColor4fv (tc->outline_color);
- glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
- tc->outline_color);
- }
- else if (front_p)
- {
- glColor4fv (t->sucker_color);
- glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
- t->sucker_color);
- }
-
- for (k = 0; k < nsuckers; k++)
- {
- double scale;
- XYZ p0 = ring[0];
- XYZ p1 = oring[0];
- XYZ p;
- p.x = p0.x + (p1.x - p0.x) * (k + 0.5) / nsuckers;
- p.y = p0.y + (p1.y - p0.y) * (k + 0.5) / nsuckers;
- p.z = p0.z + (p1.z - p0.z) * (k + 0.5) / nsuckers;
-
- glPushMatrix();
- glTranslatef (p.x, p.y, p.z);
- glRotatef (ophi * 180 / M_PI, 0, 1, 0);
- glRotatef (-oth * 180 / M_PI, 1, 0, 0);
- glRotatef (90, 1, 0, 0);
-
- { /* Not quite right: this is the slope of the outer edge
- if the next segment was not tilted at all... If there
- is any tilt, then the angle of this wall and the
- opposite wall are very different.
- */
- double slope = ((t->segments[i-1].thickness -
- t->segments[i].thickness) /
- t->segments[i].length);
- glRotatef (-45 * slope, 1, 0, 0);
- }
-
- scale = t->segments[i].thickness / arg_thickness;
- scale *= 0.7 * sucker_size;
-
- glScalef (scale, scale, scale * 4);
-
- glTranslatef (0, 0, -0.1); /* embed */
-
- if (outline_p)
- {
- scale = 1.1;
- glScalef (scale, scale, scale);
- }
-
- glTranslatef (1, 0, 0); /* left */
- draw_sucker (t, front_p);
-
- glTranslatef (-2, 0, 0); /* right */
- draw_sucker (t, front_p);
-
- glPopMatrix();
- }
-
- if (texture_p) glEnable (GL_TEXTURE_2D);
- }
- }
-
- /* Now draw the end caps.
- */
- glLineWidth (tc->line_thickness);
- if (!outline_p && (i == 0 || i == t->nsegments-1))
- {
- int j;
- GLfloat ctrz = ctr.z + ((i == 0 ? -1 : 1) *
- t->segments[i].thickness / 4);
- if (front_p)
- {
- glColor4fv (t->tentacle_color);
- glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
- t->tentacle_color);
- }
- glFrontFace ((front_p ? i == 0 : i != 0) ? GL_CCW : GL_CW);
- glBegin (wire ? GL_LINES : GL_TRIANGLE_FAN);
- glNormal3f (0, 0, (i == 0 ? -1 : 1));
- glTexCoord2f (t0 - 0.25, 0.5);
- glVertex3f (ctr.x, ctr.y, ctrz);
- for (j = 0; j <= arg_slices; j++)
- {
- int jj = j % arg_slices;
- GLfloat ts = j / (double) arg_slices;
- glTexCoord2f (t0, ts);
- glNormal3f (norm[jj].x, norm[jj].y, norm[jj].z);
- glVertex3f (ring[jj].x, ring[jj].y, ring[jj].z);
- if (wire) glVertex3f (ctr.x, ctr.y, ctrz);
- t->mi->polygon_count++;
- }
- glEnd();
- }
-
- /* Now move to the end of this segment in preparation for the next.
- */
- if (i != t->nsegments-1)
- {
- XYZ p;
- p.x = 0;
- p.y = t->segments[i].length;
- p.z = 0;
- ROT (p);
- ctr.x += p.x;
- ctr.y += p.y;
- ctr.z += p.z;
-
- /* Accumulate the current angle and rotation, to keep track of the
- rotation of the upcoming segment.
- */
- cth += t->segments[i].th;
- cphi += t->segments[i].phi;
-
- cth_sin = sin (cth);
- cth_cos = cos (cth);
- cphi_sin = sin (cphi);
- cphi_cos = cos (cphi);
-
- memcpy (oring, ring, arg_slices * sizeof(*ring));
- memcpy (onorm, norm, arg_slices * sizeof(*norm));
- }
-
- t0 = t1;
- }
-
- glPopMatrix();
-
- free (ring);
- free (norm);
- free (oring);
- free (onorm);
- free (ucirc);
-}
-
-
-static void
-draw_tentacle (tentacle *t, Bool front_p)
-{
-# ifndef HAVE_POLYGONMODE
- Bool wire = MI_IS_WIREFRAME (t->mi);
- if (!wire && cel_p && front_p)
- {
- draw_tentacle_1 (t, front_p, True);
- glClear (GL_DEPTH_BUFFER_BIT);
- }
-# endif /* HAVE_POLYGONMODE */
-
- draw_tentacle_1 (t, front_p, False);
-}
-
-
-static void
-move_tentacle (tentacle *t)
-{
- /* tentacles_configuration *tc = &tcs[MI_SCREEN(t->mi)]; */
- GLfloat len = 0;
- double pos = 0;
- int i, j;
- int skip = t->nsegments * (1 - (arg_wiggliness + 0.5));
- int tick = 0;
- int last = 0;
-
- for (i = 0; i < t->nsegments; i++)
- {
- if (++tick >= skip || i == t->nsegments-1)
- {
- /* randomize the motion of this segment... */
- double x, y, z;
- double phi_range = M_PI * 0.8 * arg_flexibility;
- double th_range = M_PI * 0.9 * arg_flexibility;
- get_position (t->segments[i].rot, &x, &y, &z, True);
- t->segments[i].phi = phi_range * (0.5 - y);
- t->segments[i].th = th_range * (0.5 - z);
- t->segments[i].length = ((0.8 + ((0.5 - x) * 0.4)) *
- (arg_length / t->nsegments));
-
- /* ...and make the previous N segments be interpolated
- between this one and the previous randomized one. */
- for (j = last+1; j <= i; j++)
- {
- t->segments[j].phi = (t->segments[i].phi / (i - last));
- t->segments[j].th = (t->segments[i].th / (i - last));
- t->segments[j].length = (t->segments[i].length);
- }
-
- tick = 0;
- last = i;
- }
- len += t->segments[i].length;
- }
-
- /* thickness of segment is relative to current position on tentacle
- (not just the index of the segment). */
- for (i = 0; i < t->nsegments; i++)
- {
- if (i > 0)
- {
- double tt = (t->segments[0].thickness * (len - pos) / len);
- if (tt < 0.001) tt = 0.001;
- t->segments[i].thickness = tt;
- }
- pos += t->segments[i].length;
- }
-}
-
-
-
-ENTRYPOINT Bool
-tentacles_handle_event (ModeInfo *mi, XEvent *event)
-{
- tentacles_configuration *tc = &tcs[MI_SCREEN(mi)];
-
- if (gltrackball_event_handler (event, tc->trackball,
- MI_WIDTH (mi), MI_HEIGHT (mi),
- &tc->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 == ' ')
- {
- gltrackball_reset (tc->trackball, 0, 0);
- return True;
- }
- }
-
- return False;
-}
-
-
-static void
-parse_color (ModeInfo *mi, const char *name, const char *s, GLfloat *a)
-{
- XColor c;
- a[3] = 1.0; /* alpha */
-
- if (! XParseColor (MI_DISPLAY(mi), MI_COLORMAP(mi), s, &c))
- {
- fprintf (stderr, "%s: can't parse %s color %s", progname, name, s);
- exit (1);
- }
- a[0] = c.red / 65536.0;
- a[1] = c.green / 65536.0;
- a[2] = c.blue / 65536.0;
-}
-
-
-ENTRYPOINT void
-init_tentacles (ModeInfo *mi)
-{
- tentacles_configuration *tc;
- int wire = MI_IS_WIREFRAME(mi);
- int i;
-
- MI_INIT (mi, tcs);
-
- tc = &tcs[MI_SCREEN(mi)];
-
- tc->glx_context = init_GL(mi);
-
- reshape_tentacles (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-
- if (!wire)
- {
- GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0};
- GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0};
- GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0};
- glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
- glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
- glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
- }
-
- if (!wire && !cel_p)
- {
- glEnable (GL_LIGHTING);
- glEnable (GL_LIGHT0);
- }
-
- tc->trackball = gltrackball_init (False);
-
- tc->left_p = !(random() % 5);
-
- if (arg_segments < 2) arg_segments = 2;
- if (arg_slices < 3) arg_slices = 3;
- if (arg_thickness < 0.1) arg_thickness = 0.1;
- if (arg_wiggliness < 0) arg_wiggliness = 0;
- if (arg_wiggliness > 1) arg_wiggliness = 1;
- if (arg_flexibility < 0) arg_flexibility = 0;
- if (arg_flexibility > 1) arg_flexibility = 1;
-
- parse_color (mi, "tentacleColor", arg_color, tc->tentacle_color);
- parse_color (mi, "stripeColor", arg_stripe, tc->stripe_color);
- parse_color (mi, "suckerColor", arg_sucker, tc->sucker_color);
-
- /* Black outlines for light colors, white outlines for dark colors. */
- if (tc->tentacle_color[0] + tc->tentacle_color[1] + tc->tentacle_color[2]
- < 0.4)
- tc->outline_color[0] = 1;
- tc->outline_color[1] = tc->outline_color[0];
- tc->outline_color[2] = tc->outline_color[0];
- tc->outline_color[3] = 1;
-
- for (i = 0; i < MI_COUNT(mi); i++)
- move_tentacle (make_tentacle (mi, i, MI_COUNT(mi)));
-
- if (wire) texture_p = cel_p = False;
- if (cel_p) texture_p = False;
-
- if (texture_p || cel_p) {
- glGenTextures(1, &tc->texid);
-# ifdef HAVE_GLBINDTEXTURE
- glBindTexture ((cel_p ? GL_TEXTURE_1D : GL_TEXTURE_2D), tc->texid);
-# endif
-
- if (cel_p)
- {
- /* "16 1 3 1",
- "X c #808080",
- "x c #C0C0C0",
- ". c #FFFFFF",
- "XXXxxxxx........"
- */
- int w = 16;
- tc->texture = XCreateImage (MI_DISPLAY(mi), MI_VISUAL(mi),
- 32, ZPixmap, 0, 0, w, 1, 32, 0);
- tc->texture->data = (char *) calloc(1, tc->texture->bytes_per_line);
- /* ABGR */
- for (i = 0; i < 3; i++) XPutPixel (tc->texture, i, 0, 0xFF808080);
- for (; i < 8; i++) XPutPixel (tc->texture, i, 0, 0xFFC0C0C0);
- for (; i < w; i++) XPutPixel (tc->texture, i, 0, 0xFFFFFFFF);
- }
- else
- tc->texture = image_data_to_ximage (MI_DISPLAY(mi), MI_VISUAL(mi),
- scales_png, sizeof(scales_png));
-
- if (!tc->texture) texture_p = cel_p = False;
- }
-
- if (texture_p) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
- clear_gl_error();
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
- tc->texture->width, tc->texture->height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, tc->texture->data);
- check_gl_error("texture");
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- glEnable(GL_TEXTURE_2D);
- } else if (cel_p) {
- clear_gl_error();
- glTexImage1D (GL_TEXTURE_1D, 0, GL_RGBA,
- tc->texture->width, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, tc->texture->data);
- check_gl_error("texture");
-
- glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- glEnable(GL_TEXTURE_1D);
- glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
- glEnable (GL_LINE_SMOOTH);
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable (GL_BLEND);
-
- /* Dark gray instead of black, so the outlines show up */
- glClearColor (0.13, 0.13, 0.13, 1.0);
- }
-
- compute_unit_torus (mi, 0.5,
- MAX(5, arg_slices/6),
- MAX(9, arg_slices/3));
-}
-
-
-ENTRYPOINT void
-draw_tentacles (ModeInfo *mi)
-{
- tentacles_configuration *tc = &tcs[MI_SCREEN(mi)];
- Display *dpy = MI_DISPLAY(mi);
- Window window = MI_WINDOW(mi);
- int i;
-
- if (!tc->glx_context)
- return;
-
- glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *tc->glx_context);
-
- glShadeModel(GL_SMOOTH);
-
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_NORMALIZE);
- glEnable(GL_CULL_FACE);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glPushMatrix ();
- glRotatef(current_device_rotation(), 0, 0, 1);
-
-# if 1
- glScalef (3, 3, 3);
-# else
- glPushAttrib (GL_ENABLE_BIT);
- glPushMatrix();
- { GLfloat s = 8.7/1600; glScalef(s,s,s); }
- glTranslatef(-800,-514,0);
- glDisable(GL_LIGHTING);
- glDisable(GL_TEXTURE_1D);
- glDisable(GL_TEXTURE_2D);
- glColor3f (1, 1, 1);
- glBegin(GL_LINE_LOOP);
- glVertex3f(0,0,0);
- glVertex3f(0,1028,0);
- glVertex3f(1600,1028,0);
- glVertex3f(1600,0,0);
- glEnd();
- glPopMatrix();
- glPopAttrib();
-# endif
-
- gltrackball_rotate (tc->trackball);
-
- mi->polygon_count = 0;
-
- if (debug_p)
- {
- glPushAttrib (GL_ENABLE_BIT);
- glDisable (GL_LIGHTING);
- glDisable (GL_TEXTURE_1D);
- glDisable (GL_TEXTURE_2D);
- glColor3f (1, 1, 1);
- glLineWidth (1);
- glBegin(GL_LINES);
- glVertex3f(-0.5, 0, 0); glVertex3f(0.5, 0, 0);
- glVertex3f(0, -0.5, 0); glVertex3f(0, 0.5, 0);
- glEnd();
- glPopAttrib();
- }
- else
- {
- GLfloat rx = 45;
- GLfloat ry = -45;
- GLfloat rz = 70;
- if (tc->left_p)
- ry = -ry, rz = -rz;
- glRotatef (ry, 0, 1, 0);
- glRotatef (rx, 1, 0, 0);
- glRotatef (rz, 0, 0, 1);
- if (intersect_p)
- glTranslatef (0, -2.0, -4.5);
- else
- glTranslatef (0, -2.5, -5.0);
- }
-
- if (!tc->button_down_p)
- for (i = 0; i < tc->ntentacles; i++)
- move_tentacle (tc->tentacles[i]);
-
-#if 1
- for (i = 0; i < tc->ntentacles; i++)
- {
- if (! intersect_p)
- glClear(GL_DEPTH_BUFFER_BIT);
- draw_tentacle (tc->tentacles[i], True);
- if (cel_p)
- draw_tentacle (tc->tentacles[i], False);
- }
-#else
- glScalef (3, 3, 3);
- glScalef (1, 1, 4);
- glColor3f(1,1,1);
- glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
- draw_sucker (tc->tentacles[0], True);
- if (cel_p)
- {
- glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
- glLineWidth (tc->line_thickness);
- glColor4fv (tc->outline_color);
- draw_sucker (tc->tentacles[0], False);
- }
-#endif
-
- glPopMatrix ();
-
- if (mi->fps_p) do_fps (mi);
- glFinish();
-
- glXSwapBuffers(dpy, window);
-}
-
-
-ENTRYPOINT void
-free_tentacles (ModeInfo *mi)
-{
- tentacles_configuration *tc = &tcs[MI_SCREEN(mi)];
- int i, j;
-
- if (!tc->glx_context) return;
- glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *tc->glx_context);
-
- for (i = 0; i < tc->ntentacles; i++) {
- for (j = 0; j < tc->tentacles[i]->nsegments; j++)
- free_rotator (tc->tentacles[i]->segments[j].rot);
- free (tc->tentacles[i]->segments);
- free (tc->tentacles[i]);
- }
- if (tc->tentacles) free (tc->tentacles);
- if (tc->torus_points) free (tc->torus_points);
- if (tc->torus_normals) free (tc->torus_normals);
- if (tc->texture) XDestroyImage (tc->texture);
- if (tc->trackball) gltrackball_free (tc->trackball);
- if (tc->texid) glDeleteTextures (1, &tc->texid);
-}
-
-XSCREENSAVER_MODULE_2 ("SkyTentacles", skytentacles, tentacles)
-
-#endif /* USE_GL */