X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fglx%2Ftunnel_draw.c;fp=hacks%2Fglx%2Ftunnel_draw.c;h=719541003a7e51ea0ffca632cf43475f77cbac77;hb=2c902d6065f9856adf31e8540a94f1e42e68e905;hp=0000000000000000000000000000000000000000;hpb=4cecfc89e5e889c7232693897c06168fb378bd5c;p=xscreensaver diff --git a/hacks/glx/tunnel_draw.c b/hacks/glx/tunnel_draw.c new file mode 100644 index 00000000..71954100 --- /dev/null +++ b/hacks/glx/tunnel_draw.c @@ -0,0 +1,472 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* atunnels --- OpenGL Advanced Tunnel Demo */ + +#if !defined( lint ) && !defined( SABER ) +static const char sccsid[] = "@(#)tunnel_draw.c 5.02 2002/03/16 xlockmore"; +#endif + +/* Copyright (c) E. Lassauge, 2002. */ + +/* + * 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 (March-16-2002) + * http://lassauge.free.fr/linux.html + * + * REVISION HISTORY: + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef USE_GL /* whole file */ + +#include +#include +#include + +#include +#include + +#include "tunnel_draw.h" + +typedef struct +{ + float x, y, z; /* Point coordinates */ +} cvPoint; + +typedef struct _tnPath +{ + cvPoint p; + struct _tnPath *next; +} tnPath; + + +tnPath *path = NULL; + +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} +}; + +/* Camera variables */ +static float cam_t=0; +static tnPath *cam_pos; +static float alpha=0; + +/* Tunnel Drawing Variables */ +static int tFlag=0; +static cvPoint prev_points[10]; +static int current_texture; + +/* Modes */ +static float ModeX=0; +static int ModeXFlag=0; + +/*=================== Vector normalization ==================================*/ +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) ==========================*/ +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; +} + +/* Catmull-Rom Curve calculations */ +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 +//========================================================================== +*/ +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(void) +{ + 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 (path == NULL) + { + path = (tnPath *)malloc(sizeof(tnPath)); + path1 = path; + } + else + { + 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; + } + + cam_pos = path; + cam_t = 0; +} + +/*=================== Tunnel Initialization ================================*/ +void InitTunnel(void) +{ + LoadPath(); + current_texture = 0; +} + +void DrawTunnel(int do_texture, int do_light, GLuint *textures) +{ + tnPath *p, *p1, *cmpos; + cvPoint op, p4[4], T, ppp, ppp1, 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[current_texture]); + + cmpos = cam_pos; + /* Get current curve */ + if (cam_pos->next->next->next) + { + p1 = 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 */ + ModeX = 1.0; + ModeXFlag = 0; + return; + }; + + /* Get current camera position */ + cvCatmullRom(p4, cam_t, &op); + + /* Next camera position */ + cam_t += 0.02f; + if (cam_t >= 1) + { + cam_t = cam_t - 1; + cmpos = 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 */ + ModeX = 1.0; + ModeXFlag = 0; + return; + } + + /* Get next camera position */ + cvCatmullRom(p4, cam_t, &op1); + + /* Rotate camera */ + glRotatef(alpha, 0, 0, -1); + 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 = 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 */ + ModeX = 1.0; + ModeXFlag = 0; + 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 */ + ModeX = 1.0; + ModeXFlag = 0; + return; + } + + cvCatmullRom(p4, t, &op1); + + ppp1.x = op1.x; + ppp1.y = op1.y; + ppp1.z = op1.z + 0.25; + + 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) + { + prev_points[i].x = op2.x; + prev_points[i].y = op2.y; + 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(prev_points[i].x, prev_points[i].y, 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(prev_points[j].x, prev_points[j].y, prev_points[j].z); + } + /* Save current polygon coordinates for next position */ + for (i=0; i<10; i++) + { + prev_points[i].x = points[i].x; + prev_points[i].y = points[i].y; + prev_points[i].z = points[i].z; + } + } + glEnd(); + cam_pos = cmpos; +} + +/* =================== Show splash screen =================================== */ +void SplashScreen(int do_wire, int do_texture, int do_light) +{ + if (ModeX > 0) + { + /* Reset tunnel and camera position */ + if (!ModeXFlag) + { + cam_pos = path; + cam_t = 0; + tFlag = 0; + ModeXFlag = 1; + current_texture++; + if (current_texture > 2) 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, 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(); + + ModeX -= 0.05; + if (ModeX <= 0) 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); + } +} +#endif