683 lines
16 KiB
C
683 lines
16 KiB
C
/* -*- Mode: C; tab-width: 4 -*- */
|
||
/* Sierpinski3D --- 3D sierpinski gasket */
|
||
|
||
#if !defined( lint ) && !defined( SABER )
|
||
static const char sccsid[] = "@(#)sierpinski3D.c 00.01 99/11/04 xlockmore";
|
||
|
||
#endif
|
||
|
||
/*-
|
||
* 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.
|
||
*
|
||
* Revision History:
|
||
*
|
||
* 06-Apr-2001 ported from Xscreensaver by Rolf Groppe <rolf@groppe.de>
|
||
*
|
||
* 1999: written by Tim Robinson <the_luggage@bigfoot.com>
|
||
* a 3-D representation of the Sierpinski gasket fractal.
|
||
*
|
||
* 10-Dec-99 jwz rewrote to draw a set of tetrahedrons instead of a
|
||
* random scattering of points.
|
||
*/
|
||
|
||
/*-
|
||
* due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock.
|
||
* otherwise caddr_t is not defined correctly
|
||
*/
|
||
|
||
#ifdef VMS
|
||
#include "vms_x_fix.h"
|
||
#include <X11/Intrinsic.h>
|
||
#endif
|
||
|
||
#ifdef STANDALONE
|
||
# define MODE_sierpinski3d
|
||
# define PROGCLASS "Sierpinski3D"
|
||
# define HACK_INIT init_gasket
|
||
# define HACK_DRAW draw_gasket
|
||
# define HACK_RESHAPE refesh_gasket
|
||
# define gasket_opts xlockmore_opts
|
||
# define DEFAULTS "*count: 1 \n" \
|
||
"*cycles: 9999 \n" \
|
||
"*delay: 15000 \n" \
|
||
"*maxDepth: 5 \n" \
|
||
"*speed: 150 \n" \
|
||
"*showFPS: False \n" \
|
||
"*wireframe: False \n"
|
||
# include "xlockmore.h" /* from the xscreensaver distribution */
|
||
#else /* !STANDALONE */
|
||
# include "xlock.h" /* from the xlockmore distribution */
|
||
#include "visgl.h"
|
||
#include "color.h"
|
||
#endif /* !STANDALONE */
|
||
|
||
#ifdef MODE_sierpinski3d
|
||
|
||
#undef countof
|
||
#define countof(x) (sizeof((x))/sizeof((*x)))
|
||
|
||
static int max_depth;
|
||
static int speed;
|
||
static int intensity;
|
||
static float intens_factor;
|
||
|
||
static XrmOptionDescRec opts[] = {
|
||
{(char *) "-maxdepth", (char *) ".sierpinski3d.maxdepth", XrmoptionSepArg, (caddr_t) 0 },
|
||
{(char *) "-speed", (char *) ".sierpinski3d.speed", XrmoptionSepArg, (caddr_t) 0 },
|
||
{(char *) "-intensity",(char *) ".sierpinski3d.intensity", XrmoptionSepArg, (caddr_t) 0}
|
||
};
|
||
|
||
static argtype vars[] = {
|
||
{(void *) &max_depth, (char *) "maxdepth", (char *) "MaxDepth",
|
||
(char *) "5", t_Int},
|
||
{(void *) &speed, (char *) "speed", (char *) "Speed",
|
||
(char *) "150", t_Int},
|
||
{(void *) &intensity, (char *) "intensity", (char *) "Intensity",
|
||
(char *) "2185", t_Int}
|
||
};
|
||
|
||
static OptionStruct desc[] = {
|
||
{(char *) "-maxdepth", (char *) "maximum depth"},
|
||
{(char *) "-speed", (char *) "speed"},
|
||
{(char *) "-intensity", (char *) "intensity"}
|
||
};
|
||
|
||
ModeSpecOpt gasket_opts = {countof(opts), opts, countof(vars), vars, desc};
|
||
|
||
#ifdef USE_MODULES
|
||
ModStruct sierpinski3d_description =
|
||
{"sierpinski3d", "init_gasket", "draw_gasket", "release_gasket",
|
||
"draw_gasket", "init_gasket", (char *) NULL, &gasket_opts,
|
||
15000, 1, 2, 1, 64, 1.0, "",
|
||
"Shows GL's Sierpinski gasket", 0, NULL};
|
||
|
||
#endif
|
||
|
||
#define FLOATRAND(a) (((double)LRAND() / (double)MAXRAND) * a)
|
||
|
||
typedef struct{
|
||
GLfloat x;
|
||
GLfloat y;
|
||
GLfloat z;
|
||
} GL_VECTOR;
|
||
|
||
typedef struct {
|
||
GLfloat rotx, roty, rotz; /* current object rotation */
|
||
GLfloat dx, dy, dz; /* current rotational velocity */
|
||
GLfloat ddx, ddy, ddz; /* current rotational acceleration */
|
||
GLfloat d_max; /* max velocity */
|
||
|
||
GLfloat angle;
|
||
GLuint gasket1;
|
||
GLXContext *glx_context;
|
||
Window window;
|
||
|
||
int current_depth;
|
||
|
||
int ncolors;
|
||
XColor *colors;
|
||
int ccolor;
|
||
|
||
} gasketstruct;
|
||
|
||
static gasketstruct *gasket = (gasketstruct *) NULL;
|
||
|
||
#include <GL/glu.h>
|
||
|
||
/* static GLuint limit; */
|
||
|
||
|
||
/* Computing normal vectors (thanks to Nat Friedman <ndf@mit.edu>)
|
||
*/
|
||
|
||
typedef struct vector {
|
||
GLfloat x, y, z;
|
||
} vector;
|
||
|
||
typedef struct plane {
|
||
vector p1, p2, p3;
|
||
} plane;
|
||
|
||
static void
|
||
vector_set(vector *v, GLfloat x, GLfloat y, GLfloat z)
|
||
{
|
||
v->x = x;
|
||
v->y = y;
|
||
v->z = z;
|
||
}
|
||
|
||
static void
|
||
vector_cross(vector v1, vector v2, vector *v3)
|
||
{
|
||
v3->x = (v1.y * v2.z) - (v1.z * v2.y);
|
||
v3->y = (v1.z * v2.x) - (v1.x * v2.z);
|
||
v3->z = (v1.x * v2.y) - (v1.y * v2.x);
|
||
}
|
||
|
||
static void
|
||
vector_subtract(vector v1, vector v2, vector *res)
|
||
{
|
||
res->x = v1.x - v2.x;
|
||
res->y = v1.y - v2.y;
|
||
res->z = v1.z - v2.z;
|
||
}
|
||
|
||
static void
|
||
plane_normal(plane p, vector *n)
|
||
{
|
||
vector v1, v2;
|
||
vector_subtract(p.p1, p.p2, &v1);
|
||
vector_subtract(p.p1, p.p3, &v2);
|
||
vector_cross(v2, v1, n);
|
||
}
|
||
|
||
static void
|
||
do_normal(GLfloat x1, GLfloat y1, GLfloat z1,
|
||
GLfloat x2, GLfloat y2, GLfloat z2,
|
||
GLfloat x3, GLfloat y3, GLfloat z3)
|
||
{
|
||
plane plane;
|
||
vector n;
|
||
vector_set(&plane.p1, x1, y1, z1);
|
||
vector_set(&plane.p2, x2, y2, z2);
|
||
vector_set(&plane.p3, x3, y3, z3);
|
||
plane_normal(plane, &n);
|
||
n.x = -n.x; n.y = -n.y; n.z = -n.z;
|
||
|
||
glNormal3f(n.x, n.y, n.z);
|
||
|
||
#ifdef DEBUG
|
||
/* Draw a line in the direction of this face's normal. */
|
||
{
|
||
GLfloat ax = n.x > 0 ? n.x : -n.x;
|
||
GLfloat ay = n.y > 0 ? n.y : -n.y;
|
||
GLfloat az = n.z > 0 ? n.z : -n.z;
|
||
GLfloat mx = (x1 + x2 + x3) / 3;
|
||
GLfloat my = (y1 + y2 + y3) / 3;
|
||
GLfloat mz = (z1 + z2 + z3) / 3;
|
||
GLfloat xx, yy, zz;
|
||
|
||
GLfloat max = ax > ay ? ax : ay;
|
||
if (az > max) max = az;
|
||
max *= 2;
|
||
xx = n.x / max;
|
||
yy = n.y / max;
|
||
zz = n.z / max;
|
||
|
||
glBegin(GL_LINE_LOOP);
|
||
glVertex3f(mx, my, mz);
|
||
glVertex3f(mx+xx, my+yy, mz+zz);
|
||
glEnd();
|
||
}
|
||
#endif /* DEBUG */
|
||
}
|
||
|
||
|
||
|
||
static void
|
||
triangle (GLfloat x1, GLfloat y1, GLfloat z1,
|
||
GLfloat x2, GLfloat y2, GLfloat z2,
|
||
GLfloat x3, GLfloat y3, GLfloat z3,
|
||
Bool wireframe_p)
|
||
{
|
||
if (wireframe_p)
|
||
glBegin (GL_LINE_LOOP);
|
||
else
|
||
{
|
||
do_normal (x1, y1, z1, x2, y2, z2, x3, y3, z3);
|
||
glBegin (GL_TRIANGLES);
|
||
}
|
||
glVertex3f (x1, y1, z1);
|
||
glVertex3f (x2, y2, z2);
|
||
glVertex3f (x3, y3, z3);
|
||
glEnd();
|
||
}
|
||
|
||
static void
|
||
four_tetras (GL_VECTOR *outer, Bool wireframe_p, int countdown)
|
||
{
|
||
if (countdown <= 0)
|
||
{
|
||
triangle (outer[0].x, outer[0].y, outer[0].z,
|
||
outer[1].x, outer[1].y, outer[1].z,
|
||
outer[2].x, outer[2].y, outer[2].z,
|
||
wireframe_p);
|
||
triangle (outer[0].x, outer[0].y, outer[0].z,
|
||
outer[3].x, outer[3].y, outer[3].z,
|
||
outer[1].x, outer[1].y, outer[1].z,
|
||
wireframe_p);
|
||
triangle (outer[0].x, outer[0].y, outer[0].z,
|
||
outer[2].x, outer[2].y, outer[2].z,
|
||
outer[3].x, outer[3].y, outer[3].z,
|
||
wireframe_p);
|
||
triangle (outer[1].x, outer[1].y, outer[1].z,
|
||
outer[3].x, outer[3].y, outer[3].z,
|
||
outer[2].x, outer[2].y, outer[2].z,
|
||
wireframe_p);
|
||
}
|
||
else
|
||
{
|
||
# define M01 0
|
||
# define M02 1
|
||
# define M03 2
|
||
# define M12 3
|
||
# define M13 4
|
||
# define M23 5
|
||
GL_VECTOR inner[M23+1];
|
||
GL_VECTOR corner[4];
|
||
|
||
inner[M01].x = (outer[0].x + outer[1].x) / 2.0;
|
||
inner[M01].y = (outer[0].y + outer[1].y) / 2.0;
|
||
inner[M01].z = (outer[0].z + outer[1].z) / 2.0;
|
||
|
||
inner[M02].x = (outer[0].x + outer[2].x) / 2.0;
|
||
inner[M02].y = (outer[0].y + outer[2].y) / 2.0;
|
||
inner[M02].z = (outer[0].z + outer[2].z) / 2.0;
|
||
|
||
inner[M03].x = (outer[0].x + outer[3].x) / 2.0;
|
||
inner[M03].y = (outer[0].y + outer[3].y) / 2.0;
|
||
inner[M03].z = (outer[0].z + outer[3].z) / 2.0;
|
||
|
||
inner[M12].x = (outer[1].x + outer[2].x) / 2.0;
|
||
inner[M12].y = (outer[1].y + outer[2].y) / 2.0;
|
||
inner[M12].z = (outer[1].z + outer[2].z) / 2.0;
|
||
|
||
inner[M13].x = (outer[1].x + outer[3].x) / 2.0;
|
||
inner[M13].y = (outer[1].y + outer[3].y) / 2.0;
|
||
inner[M13].z = (outer[1].z + outer[3].z) / 2.0;
|
||
|
||
inner[M23].x = (outer[2].x + outer[3].x) / 2.0;
|
||
inner[M23].y = (outer[2].y + outer[3].y) / 2.0;
|
||
inner[M23].z = (outer[2].z + outer[3].z) / 2.0;
|
||
|
||
countdown--;
|
||
|
||
corner[0] = outer[0];
|
||
corner[1] = inner[M01];
|
||
corner[2] = inner[M02];
|
||
corner[3] = inner[M03];
|
||
four_tetras (corner, wireframe_p, countdown);
|
||
|
||
corner[0] = inner[M01];
|
||
corner[1] = outer[1];
|
||
corner[2] = inner[M12];
|
||
corner[3] = inner[M13];
|
||
four_tetras (corner, wireframe_p, countdown);
|
||
|
||
corner[0] = inner[M02];
|
||
corner[1] = inner[M12];
|
||
corner[2] = outer[2];
|
||
corner[3] = inner[M23];
|
||
four_tetras (corner, wireframe_p, countdown);
|
||
|
||
corner[0] = inner[M03];
|
||
corner[1] = inner[M13];
|
||
corner[2] = inner[M23];
|
||
corner[3] = outer[3];
|
||
four_tetras (corner, wireframe_p, countdown);
|
||
}
|
||
}
|
||
|
||
|
||
static void
|
||
compile_gasket(ModeInfo *mi)
|
||
{
|
||
Bool wireframe_p = MI_IS_WIREFRAME(mi);
|
||
gasketstruct *gp = &gasket[MI_SCREEN(mi)];
|
||
|
||
GL_VECTOR vertex[5];
|
||
|
||
/* define verticies */
|
||
vertex[0].x = 0.5;
|
||
vertex[0].y = -(1.0/3.0)*sqrt((2.0/3.0));
|
||
vertex[0].z = -sqrt(3.0)/6.0;
|
||
|
||
vertex[1].x = -0.5;
|
||
vertex[1].y = -(1.0/3.0)*sqrt((2.0/3.0));
|
||
vertex[1].z = -sqrt(3.0)/6.0;
|
||
|
||
vertex[2].x = 0.0;
|
||
vertex[2].y = (2.0/3.0)*sqrt((2.0/3.0));
|
||
vertex[2].z = -sqrt(3.0)/6.0;
|
||
|
||
vertex[3].x = 0.0;
|
||
vertex[3].y = 0.0;
|
||
vertex[3].z = sqrt(3.0)/3.0;
|
||
|
||
vertex[4].x = 0.0;
|
||
vertex[4].y = 0.0;
|
||
vertex[4].z = 0.0;
|
||
|
||
four_tetras (vertex, wireframe_p,
|
||
(gp->current_depth < 0
|
||
? -gp->current_depth : gp->current_depth));
|
||
}
|
||
|
||
static void
|
||
draw(ModeInfo *mi)
|
||
{
|
||
Bool wireframe_p = MI_IS_WIREFRAME(mi);
|
||
gasketstruct *gp = &gasket[MI_SCREEN(mi)];
|
||
static int tick = 0;
|
||
|
||
static GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0};
|
||
static float white[] = {1.0, 1.0, 1.0, 1.0};
|
||
static float color[] = {0.0, 0.0, 0.0, 1.0};
|
||
|
||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||
|
||
if (!wireframe_p)
|
||
{
|
||
glColor4fv (white);
|
||
|
||
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
||
|
||
color[0] = gp->colors[gp->ccolor].red * intens_factor;
|
||
color[1] = gp->colors[gp->ccolor].green * intens_factor;
|
||
color[2] = gp->colors[gp->ccolor].blue * intens_factor;
|
||
gp->ccolor++;
|
||
if (gp->ccolor >= gp->ncolors) gp->ccolor = 0;
|
||
|
||
glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
|
||
|
||
glShadeModel(GL_SMOOTH);
|
||
|
||
glEnable(GL_LIGHTING);
|
||
glEnable(GL_LIGHT0);
|
||
}
|
||
|
||
glEnable(GL_DEPTH_TEST);
|
||
glEnable(GL_NORMALIZE);
|
||
glEnable(GL_CULL_FACE);
|
||
|
||
glPushMatrix();
|
||
|
||
{
|
||
static int frame = 0;
|
||
GLfloat x, y, z;
|
||
|
||
# define SINOID(SCALE,SIZE) \
|
||
((((1 + sin((frame * (SCALE)) / 2 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2)
|
||
x = SINOID(0.0071, 8.0);
|
||
y = SINOID(0.0053, 6.0);
|
||
z = SINOID(0.0037, 15.0);
|
||
frame++;
|
||
glTranslatef(x, y, z);
|
||
|
||
x = gp->rotx;
|
||
y = gp->roty;
|
||
z = gp->rotz;
|
||
if (x < 0) x = 1 - (x + 1);
|
||
if (y < 0) y = 1 - (y + 1);
|
||
if (z < 0) z = 1 - (z + 1);
|
||
glRotatef(x * 360, 1.0, 0.0, 0.0);
|
||
glRotatef(y * 360, 0.0, 1.0, 0.0);
|
||
glRotatef(z * 360, 0.0, 0.0, 1.0);
|
||
}
|
||
|
||
glScalef( 8.0, 8.0, 8.0 );
|
||
glCallList(gp->gasket1);
|
||
|
||
glPopMatrix();
|
||
|
||
|
||
if (tick++ >= speed)
|
||
{
|
||
|
||
tick = 0;
|
||
if (gp->current_depth >= max_depth)
|
||
gp->current_depth = -max_depth;
|
||
gp->current_depth++;
|
||
|
||
glDeleteLists (gp->gasket1, 1);
|
||
glNewList (gp->gasket1, GL_COMPILE);
|
||
compile_gasket (mi);
|
||
glEndList();
|
||
|
||
}
|
||
}
|
||
|
||
|
||
/* new window size or exposure */
|
||
void
|
||
reshape_gasket(ModeInfo *mi, int width, int height)
|
||
{
|
||
GLfloat h = (GLfloat) height / (GLfloat) width;
|
||
|
||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||
glMatrixMode(GL_PROJECTION);
|
||
glLoadIdentity();
|
||
|
||
gluPerspective( 30.0, 1/h, 1.0, 100.0 );
|
||
gluLookAt( 0.0, 0.0, 15.0,
|
||
0.0, 0.0, 0.0,
|
||
0.0, 1.0, 0.0);
|
||
glMatrixMode(GL_MODELVIEW);
|
||
glLoadIdentity();
|
||
glTranslatef(0.0, 0.0, -15.0);
|
||
|
||
glClear(GL_COLOR_BUFFER_BIT);
|
||
}
|
||
|
||
static void
|
||
pinit(ModeInfo *mi)
|
||
{
|
||
gasketstruct *gp = &gasket[MI_SCREEN(mi)];
|
||
|
||
/* draw the gasket */
|
||
gp->gasket1 = glGenLists(1);
|
||
gp->current_depth = 1; /* start out at level 1, not 0 */
|
||
glNewList(gp->gasket1, GL_COMPILE);
|
||
compile_gasket(mi);
|
||
glEndList();
|
||
}
|
||
|
||
|
||
|
||
/* lifted from lament.c */
|
||
#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
|
||
#define RANDSIGN() ((random() & 1) ? 1 : -1)
|
||
|
||
static void
|
||
rotate(GLfloat *pos, GLfloat *v, GLfloat *dv, GLfloat max_v, Bool verbose)
|
||
{
|
||
double ppos = *pos;
|
||
|
||
/* tick position */
|
||
if (ppos < 0)
|
||
ppos = -(ppos + *v);
|
||
else
|
||
ppos += *v;
|
||
|
||
if (ppos > 1.0)
|
||
ppos -= 1.0;
|
||
else if (ppos < 0)
|
||
ppos += 1.0;
|
||
|
||
if ((ppos < 0.0) || (ppos > 1.0)) {
|
||
if (verbose) {
|
||
(void) fprintf(stderr, "Weirdness in rotate()\n");
|
||
(void) fprintf(stderr, "ppos = %g\n", ppos);
|
||
}
|
||
return;
|
||
}
|
||
*pos = (*pos > 0 ? ppos : -ppos);
|
||
|
||
/* accelerate */
|
||
*v += *dv;
|
||
|
||
/* clamp velocity */
|
||
if (*v > max_v || *v < -max_v)
|
||
{
|
||
*dv = -*dv;
|
||
}
|
||
/* If it stops, start it going in the other direction. */
|
||
else if (*v < 0)
|
||
{
|
||
if (random() % 4)
|
||
{
|
||
*v = 0;
|
||
|
||
/* keep going in the same direction */
|
||
if (random() % 2)
|
||
*dv = 0;
|
||
else if (*dv < 0)
|
||
*dv = -*dv;
|
||
}
|
||
else
|
||
{
|
||
/* reverse gears */
|
||
*v = -*v;
|
||
*dv = -*dv;
|
||
*pos = -*pos;
|
||
}
|
||
}
|
||
|
||
/* Alter direction of rotational acceleration randomly. */
|
||
if (! (random() % 120))
|
||
*dv = -*dv;
|
||
|
||
/* Change acceleration very occasionally. */
|
||
if (! (random() % 200))
|
||
{
|
||
if (*dv == 0)
|
||
*dv = 0.00001;
|
||
else if (random() & 1)
|
||
*dv *= 1.2;
|
||
else
|
||
*dv *= 0.8;
|
||
}
|
||
}
|
||
|
||
|
||
void
|
||
init_gasket(ModeInfo *mi)
|
||
{
|
||
int screen = MI_SCREEN(mi);
|
||
gasketstruct *gp;
|
||
|
||
if (gasket == NULL)
|
||
{
|
||
if ((gasket = (gasketstruct *) calloc(MI_NUM_SCREENS(mi),
|
||
sizeof (gasketstruct))) == NULL)
|
||
return;
|
||
}
|
||
gp = &gasket[screen];
|
||
|
||
gp->window = MI_WINDOW(mi);
|
||
|
||
gp->rotx = FLOATRAND(1.0) * RANDSIGN();
|
||
gp->roty = FLOATRAND(1.0) * RANDSIGN();
|
||
gp->rotz = FLOATRAND(1.0) * RANDSIGN();
|
||
|
||
/* bell curve from 0-1.5 degrees, avg 0.75 */
|
||
gp->dx = (FLOATRAND(1) + FLOATRAND(1) + FLOATRAND(1)) / (360*2);
|
||
gp->dy = (FLOATRAND(1) + FLOATRAND(1) + FLOATRAND(1)) / (360*2);
|
||
gp->dz = (FLOATRAND(1) + FLOATRAND(1) + FLOATRAND(1)) / (360*2);
|
||
|
||
gp->d_max = gp->dx * 2;
|
||
|
||
gp->ddx = 0.00006 + FLOATRAND(0.00003);
|
||
gp->ddy = 0.00006 + FLOATRAND(0.00003);
|
||
gp->ddz = 0.00006 + FLOATRAND(0.00003);
|
||
|
||
gp->ddx = 0.00001;
|
||
gp->ddy = 0.00001;
|
||
gp->ddz = 0.00001;
|
||
|
||
intens_factor = intensity / 65536000.0;
|
||
gp->ncolors = 255;
|
||
gp->colors = (XColor *) calloc(gp->ncolors, sizeof(XColor));
|
||
make_smooth_colormap (mi, None,
|
||
gp->colors, &gp->ncolors,
|
||
False, (Bool *) NULL);
|
||
|
||
if ((gp->glx_context = init_GL(mi)) != NULL)
|
||
{
|
||
reshape_gasket(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
|
||
pinit(mi);
|
||
}
|
||
else
|
||
{
|
||
MI_CLEARWINDOW(mi);
|
||
}
|
||
}
|
||
|
||
void
|
||
draw_gasket(ModeInfo * mi)
|
||
{
|
||
gasketstruct *gp = &gasket[MI_SCREEN(mi)];
|
||
Display *display = MI_DISPLAY(mi);
|
||
Window window = MI_WINDOW(mi);
|
||
int angle_incr = 1;
|
||
|
||
if (!gp->glx_context) return;
|
||
|
||
glDrawBuffer(GL_BACK);
|
||
|
||
if (max_depth > 10)
|
||
max_depth = 10;
|
||
|
||
MI_IS_DRAWN(mi) = True;
|
||
|
||
glXMakeCurrent(display, window, *(gp->glx_context));
|
||
draw(mi);
|
||
|
||
/* rotate */
|
||
gp->angle = (int) (gp->angle + angle_incr) % 360;
|
||
|
||
rotate(&gp->rotx, &gp->dx, &gp->ddx, gp->d_max, MI_IS_VERBOSE(mi));
|
||
rotate(&gp->roty, &gp->dy, &gp->ddy, gp->d_max, MI_IS_VERBOSE(mi));
|
||
rotate(&gp->rotz, &gp->dz, &gp->ddz, gp->d_max, MI_IS_VERBOSE(mi));
|
||
|
||
/* if (mi->fps_p) do_fps (mi); */
|
||
|
||
if (MI_IS_FPS(mi)) do_fps (mi);
|
||
glFinish();
|
||
glXSwapBuffers(display, window);
|
||
}
|
||
|
||
void
|
||
release_gasket(ModeInfo * mi)
|
||
{
|
||
if (gasket != NULL)
|
||
{
|
||
int screen;
|
||
|
||
for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
|
||
{
|
||
gasketstruct *gp = &gasket[screen];
|
||
|
||
if (gp->colors != NULL) {
|
||
XFree((caddr_t) gp->colors);
|
||
gp->colors = (XColor *) NULL;
|
||
}
|
||
if (gp->glx_context)
|
||
{
|
||
/* Display lists MUST be freed while their glXContext is current. */
|
||
glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context));
|
||
|
||
if (glIsList(gp->gasket1)) glDeleteLists(gp->gasket1, 1);
|
||
}
|
||
}
|
||
free(gasket);
|
||
gasket = (gasketstruct *) NULL;
|
||
}
|
||
FreeAllGL(mi);
|
||
}
|
||
|
||
|
||
/*********************************************************/
|
||
|
||
#endif
|