summaryrefslogtreecommitdiffstats
path: root/hacks/glx/tunnel_draw.c
diff options
context:
space:
mode:
Diffstat (limited to 'hacks/glx/tunnel_draw.c')
-rw-r--r--hacks/glx/tunnel_draw.c512
1 files changed, 512 insertions, 0 deletions
diff --git a/hacks/glx/tunnel_draw.c b/hacks/glx/tunnel_draw.c
new file mode 100644
index 0000000..8a87c76
--- /dev/null
+++ b/hacks/glx/tunnel_draw.c
@@ -0,0 +1,512 @@
+/* -*- Mode: C; tab-width: 4 -*- */
+/* atunnels --- OpenGL Advanced Tunnel Demo */
+
+#if 0
+static const char sccsid[] = "@(#)tunnel_draw.c 5.13 2004/05/25 xlockmore";
+#endif
+
+/* Copyright (c) E. Lassauge, 2002-2004. */
+
+/*
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * This file is provided AS IS with no warranties of any kind. The author
+ * shall have no liability with respect to the infringement of copyrights,
+ * trade secrets or any patents by this file or any part thereof. In no
+ * event will the author be liable for any lost revenue or profits or
+ * other special, indirect and consequential damages.
+ *
+ * The original code for this mode was written by Roman Podobedov
+ * Email: romka@ut.ee
+ * WEB: http://romka.demonews.com
+ *
+ * Eric Lassauge (May-25-2004) <lassauge@users.sourceforge.net>
+ * http://lassauge.free.fr/linux.html
+ *
+ * REVISION HISTORY:
+ * E.Lassauge - 25-May-2004:
+ * - added more texture
+ * - random texture init
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef USE_GL /* whole file */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef STANDALONE
+# ifndef HAVE_JWXYZ
+# include <GL/gl.h>
+# include <GL/glu.h>
+# endif
+#endif
+#ifdef HAVE_ANDROID
+#include <GLES/gl.h>
+#endif
+
+
+#include "tunnel_draw.h"
+
+#ifdef STANDALONE /* For NRAND() */
+#include "xlockmoreI.h" /* in xscreensaver distribution */
+#else /* STANDALONE */
+#include "xlock.h" /* in xlockmore distribution */
+#endif /* STANDALONE */
+
+typedef struct
+{
+ float x, y, z; /* Point coordinates */
+} cvPoint;
+
+typedef struct _tnPath
+{
+ cvPoint p;
+ struct _tnPath *next;
+} tnPath;
+
+
+static const cvPoint initpath[]={
+{0.000000, 0.000000, 0.000000},
+{2.000000, 1.000000, 0.000000},
+{4.000000, 0.000000, 0.000000},
+{6.000000, 1.000000, 0.000000},
+{8.000000, 0.000000, 1.000000},
+{10.000000, 1.000000, 1.000000},
+{12.000000, 1.500000, 0.000000},
+{14.000000, 0.000000, 0.000000},
+{16.000000, 1.000000, 0.000000},
+{18.000000, 0.000000, 0.000000},
+{20.000000, 0.000000, 1.000000},
+{22.000000, 1.000000, 0.000000},
+{24.000000, 0.000000, 1.000000},
+{26.000000, 0.000000, 1.000000},
+{28.000000, 1.000000, 0.000000},
+{30.000000, 0.000000, 2.000000},
+{32.000000, 1.000000, 0.000000},
+{34.000000, 0.000000, 2.000000},
+{-1.000000, -1.000000, -1.000000}
+};
+
+
+struct tunnel_state {
+
+ tnPath *path;
+
+ float cam_t; /* Camera variables */
+ tnPath *cam_pos;
+ float alpha;
+
+ int tFlag; /* Tunnel Drawing Variables */
+ cvPoint prev_points[10];
+ int current_texture;
+
+ float ModeX; /* Modes */
+ int ModeXFlag;
+};
+
+/*=================== Vector normalization ==================================*/
+static void
+normalize(cvPoint *V)
+{
+ float d;
+
+ /* Vector length */
+ d = (float)sqrt(V->x*V->x + V->y*V->y + V->z*V->z);
+
+ /* Normalization */
+ V->x /= d;
+ V->y /= d;
+ V->z /= d;
+}
+/*=================== C = A x B (Vector multiply) ==========================*/
+#if 0
+static void
+vect_mult(cvPoint *A, cvPoint *B, cvPoint *C)
+{
+ /* Vector multiply */
+ C->x = A->y*B->z - A->z*B->y;
+ C->y = A->z*B->x - A->x*B->z;
+ C->z = A->x*B->y - A->y*B->x;
+}
+#endif
+
+/* Catmull-Rom Curve calculations */
+static void
+cvCatmullRom(cvPoint *p, float t, cvPoint *outp)
+{
+ float t2, t3, t1;
+
+ t2 = t*t;
+ t3 = t*t*t;
+ t1 = (1-t)*(1-t);
+
+ outp->x = (-t*t1*p[0].x + (2-5*t2+3*t3)*p[1].x + t*(1+4*t-3*t2)*p[2].x - t2*(1-t)*p[3].x)/2;
+ outp->y = (-t*t1*p[0].y + (2-5*t2+3*t3)*p[1].y + t*(1+4*t-3*t2)*p[2].y - t2*(1-t)*p[3].y)/2;
+ outp->z = (-t*t1*p[0].z + (2-5*t2+3*t3)*p[1].z + t*(1+4*t-3*t2)*p[2].z - t2*(1-t)*p[3].z)/2;
+}
+
+/*=================== Point Rotating Around Line ===========================
+// p - original point
+// pp - pivot point
+// pl - pivot line (vector)
+// a - angle to rotate in radians
+// outp - output point
+//==========================================================================
+*/
+static void
+RotateAroundLine(cvPoint *p, cvPoint *pp, cvPoint *pl, float a, cvPoint *outp)
+{
+ cvPoint p1, p2;
+ float l, m, n, ca, sa;
+
+ p1.x = p->x - pp->x;
+ p1.y = p->y - pp->y;
+ p1.z = p->z - pp->z;
+
+ l = pl->x;
+ m = pl->y;
+ n = pl->z;
+
+ ca = cos(a);
+ sa = sin(a);
+
+ p2.x = p1.x*((l*l)+ca*(1-l*l)) + p1.y*(l*(1-ca)*m+n*sa) + p1.z*(l*(1-ca)*n-m*sa);
+ p2.y = p1.x*(l*(1-ca)*m-n*sa) + p1.y*(m*m+ca*(1-m*m)) + p1.z*(m*(1-ca)*n+l*sa);
+ p2.z = p1.x*(l*(1-ca)*n+m*sa) + p1.y*(m*(1-ca)*n-l*sa) + p1.z*(n*n+ca*(1-n*n));
+
+ outp->x = p2.x + pp->x;
+ outp->y = p2.y + pp->y;
+ outp->z = p2.z + pp->z;
+}
+
+
+/*=================== Load camera and tunnel path ==========================*/
+static void
+LoadPath(struct tunnel_state *st)
+{
+ float x, y, z;
+ tnPath *path1=NULL, *path2=NULL;
+
+ cvPoint *f = (cvPoint *)initpath;
+
+ while (f->x != -1.0)
+ {
+ x = f->x;
+ y = f->y;
+ z = f->z;
+ f++;
+
+ if (st->path == NULL)
+ {
+ st->path = (tnPath *)malloc(sizeof(tnPath));
+ path1 = st->path;
+ }
+ else
+ {
+ if (!path1) path1 = st->path;
+ path2 = (tnPath *)malloc(sizeof(tnPath));
+ path1->next = path2;
+ path1 = path2;
+ }
+
+ path1->next = NULL;
+ path1->p.x = x;
+ path1->p.y = y;
+ path1->p.z = z;
+ }
+
+ st->cam_pos = st->path;
+ st->cam_t = 0;
+}
+
+/*=================== Tunnel Initialization ================================*/
+struct tunnel_state *
+atunnel_InitTunnel(void)
+{
+ struct tunnel_state *st = (struct tunnel_state *) calloc (1, sizeof(*st));
+ LoadPath(st);
+ st->current_texture = NRAND(MAX_TEXTURE);
+ return st;
+}
+
+void
+atunnel_DrawTunnel(struct tunnel_state *st,
+ int do_texture, int do_light, GLuint *textures)
+{
+ tnPath *p, *p1, *cmpos;
+ cvPoint op, p4[4], T, ppp, op1, op2;
+ float t;
+ int i, j, k, flag;
+ cvPoint points[10];
+ GLfloat light_position[4];
+
+
+ /* Select current tunnel texture */
+ if (do_texture)
+ glBindTexture(GL_TEXTURE_2D, textures[st->current_texture]);
+
+ cmpos = st->cam_pos;
+ /* Get current curve */
+ if (st->cam_pos->next &&
+ st->cam_pos->next->next &&
+ st->cam_pos->next->next->next)
+ {
+ p1 = st->cam_pos;
+ for (i=0; i<4; i++)
+ {
+ p4[i].x = p1->p.x;
+ p4[i].y = p1->p.y;
+ p4[i].z = p1->p.z;
+ p1 = p1->next;
+ }
+ }
+ else
+ {
+ /* End of tunnel */
+ st->ModeX = 1.0;
+ st->ModeXFlag = 0;
+ return;
+ };
+
+ /* Get current camera position */
+ cvCatmullRom(p4, st->cam_t, &op);
+
+ /* Next camera position */
+ st->cam_t += 0.02f;
+ if (st->cam_t >= 1)
+ {
+ st->cam_t = st->cam_t - 1;
+ cmpos = st->cam_pos->next;
+ }
+
+ /* Get curve for next camera position */
+ if (cmpos->next->next->next)
+ {
+ p1 = cmpos;
+ for (i=0; i<4; i++)
+ {
+ p4[i].x = p1->p.x;
+ p4[i].y = p1->p.y;
+ p4[i].z = p1->p.z;
+ p1 = p1->next;
+ }
+ }
+ else
+ {
+ /* End of tunnel */
+ st->ModeX = 1.0;
+ st->ModeXFlag = 0;
+ return;
+ }
+
+ /* Get next camera position */
+ cvCatmullRom(p4, st->cam_t, &op1);
+
+ /* Rotate camera */
+ glRotatef(st->alpha, 0, 0, -1);
+ st->alpha += 1;
+ /* Set camera position */
+ gluLookAt(op.x, op.y, op.z, op1.x, op1.y, op1.z, 0, 1, 0);
+
+ /* Set light position */
+ if (do_light)
+ {
+ light_position[0] = op.x;
+ light_position[1] = op.y;
+ light_position[2] = op.z;
+ light_position[3] = 1;
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position);
+ }
+
+ p = st->cam_pos;
+ flag = 0;
+ t = 0;
+ k = 0;
+ /* Draw tunnel from current curve and next 2 curves */
+ glBegin(GL_QUADS);
+ while (k < 3)
+ {
+ if (p->next->next->next)
+ {
+ p1 = p;
+ for (i=0; i<4; i++)
+ {
+ p4[i].x = p1->p.x;
+ p4[i].y = p1->p.y;
+ p4[i].z = p1->p.z;
+ p1 = p1->next;
+ }
+ }
+ else
+ {
+ /* End of tunnel */
+ st->ModeX = 1.0;
+ st->ModeXFlag = 0;
+ glEnd();
+ return;
+ }
+ cvCatmullRom(p4, t, &op);
+
+ ppp.x = op.x;
+ ppp.y = op.y;
+ ppp.z = op.z + 0.25;
+
+ t += 0.1;
+ if (t >= 1.0)
+ {
+ t = t - 1;
+ k++;
+ p = p->next;
+ }
+
+ if (p->next->next->next)
+ {
+ p1 = p;
+ for (i=0; i<4; i++)
+ {
+ p4[i].x = p1->p.x;
+ p4[i].y = p1->p.y;
+ p4[i].z = p1->p.z;
+ p1 = p1->next;
+ }
+ }
+ else
+ {
+ /* End of tunnel */
+ st->ModeX = 1.0;
+ st->ModeXFlag = 0;
+ glEnd();
+ return;
+ }
+
+ cvCatmullRom(p4, t, &op1);
+
+ T.x = op1.x - op.x;
+ T.y = op1.y - op.y;
+ T.z = op1.z - op.z;
+
+ normalize(&T);
+
+ for (i=0; i<10; i++)
+ {
+ RotateAroundLine(&ppp, &op, &T, ((float)i*36.0*M_PI/180.0), &op2);
+ points[i].x = op2.x;
+ points[i].y = op2.y;
+ points[i].z = op2.z;
+ if (!flag)
+ {
+ st->prev_points[i].x = op2.x;
+ st->prev_points[i].y = op2.y;
+ st->prev_points[i].z = op2.z;
+ }
+ }
+
+ if (!flag)
+ {
+ flag = 1;
+ continue;
+ }
+
+ /* Draw 10 polygons for current point */
+ for (i=0; i<10; i++)
+ {
+ j = i+1;
+ if (j > 9) j = 0;
+ glNormal3f(0, 0, 1); /* Normal for lighting */
+ glTexCoord2f(0, 0); glVertex3f(st->prev_points[i].x, st->prev_points[i].y, st->prev_points[i].z);
+ glNormal3f(0, 0, 1);
+ glTexCoord2f(1, 0); glVertex3f(points[i].x, points[i].y, points[i].z);
+ glNormal3f(0, 0, 1);
+ glTexCoord2f(1, 1); glVertex3f(points[j].x, points[j].y, points[j].z);
+ glNormal3f(0, 0, 1);
+ glTexCoord2f(0, 1); glVertex3f(st->prev_points[j].x, st->prev_points[j].y, st->prev_points[j].z);
+ }
+ /* Save current polygon coordinates for next position */
+ for (i=0; i<10; i++)
+ {
+ st->prev_points[i].x = points[i].x;
+ st->prev_points[i].y = points[i].y;
+ st->prev_points[i].z = points[i].z;
+ }
+ }
+ glEnd();
+ st->cam_pos = cmpos;
+}
+
+/* =================== Show splash screen =================================== */
+void
+atunnel_SplashScreen(struct tunnel_state *st,
+ int do_wire, int do_texture, int do_light)
+{
+ if (st->ModeX > 0)
+ {
+ /* Reset tunnel and camera position */
+ if (!st->ModeXFlag)
+ {
+ st->cam_pos = st->path;
+ st->cam_t = 0;
+ st->tFlag = 0;
+ st->ModeXFlag = 1;
+ st->current_texture++;
+ if (st->current_texture >= MAX_TEXTURE) st->current_texture = 0;
+ }
+ /* Now we want to draw splash screen */
+ glLoadIdentity();
+ /* Disable all unused features */
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_FOG);
+ glDisable(GL_CULL_FACE);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
+ glEnable(GL_BLEND);
+ glDisable(GL_TEXTURE_2D);
+ glColor4f(1, 1, 1, st->ModeX);
+
+ /* Draw splash screen (simply quad) */
+ glBegin(GL_QUADS);
+ glVertex3f(-10, -10, -1);
+ glVertex3f(10, -10, -1);
+ glVertex3f(10, 10, -1);
+ glVertex3f(-10, 10, -1);
+ glEnd();
+
+ st->ModeX -= 0.05;
+ if (st->ModeX <= 0) st->ModeX = 0;
+
+ if (!do_wire)
+ {
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+ }
+ if (do_light)
+ {
+ glEnable(GL_LIGHTING);
+ glEnable(GL_FOG);
+ }
+ if (do_texture)
+ {
+ glEnable(GL_TEXTURE_2D);
+ }
+ glDisable(GL_BLEND);
+ glColor4f(1, 1, 1, 1);
+ }
+}
+
+void
+atunnel_FreeTunnel(struct tunnel_state *st)
+{
+ free (st);
+}
+
+#endif