1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* Sierpinski3D --- 3D sierpinski gasket */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)sierpinski3D.c 00.01 99/11/04 xlockmore";
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation for any purpose and without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and that
13 * both that copyright notice and this permission notice appear in
14 * supporting documentation.
16 * This file is provided AS IS with no warranties of any kind. The author
17 * shall have no liability with respect to the infringement of copyrights,
18 * trade secrets or any patents by this file or any part thereof. In no
19 * event will the author be liable for any lost revenue or profits or
20 * other special, indirect and consequential damages.
23 * 1999: written by Tim Robinson <the_luggage@bigfoot.com>
24 * a 3-D representation of the Sierpinski gasket fractal.
28 * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock.
29 * otherwise caddr_t is not defined correctly
32 #include <X11/Intrinsic.h>
35 # define PROGCLASS "Sierpinski3D"
36 # define HACK_INIT init_gasket
37 # define HACK_DRAW draw_gasket
38 # define gasket_opts xlockmore_opts
39 # define DEFAULTS "*count: 1 \n" \
42 "*wireframe: False \n"
43 # include "xlockmore.h" /* from the xscreensaver distribution */
44 #else /* !STANDALONE */
45 # include "xlock.h" /* from the xlockmore distribution */
46 #endif /* !STANDALONE */
50 ModeSpecOpt gasket_opts =
51 {0, NULL, 0, NULL, NULL};
54 ModStruct gasket_description =
55 {"gasket", "init_gasket", "draw_gasket", "release_gasket",
56 "draw_gasket", "init_gasket", NULL, &gasket_opts,
57 1000, 1, 2, 1, 4, 1.0, "",
58 "Shows GL's Sierpinski gasket", 0, NULL};
69 GLfloat view_rotx, view_roty, view_rotz;
70 GLfloat light_colour[4];/* = {6.0, 6.0, 6.0, 1.0}; */
71 GLfloat pos[3];/* = {0.0, 0.0, 0.0}; */
72 GLfloat xinc,yinc,zinc;
75 GLXContext *glx_context;
82 static gasketstruct *gasket = NULL;
86 /* static GLuint limit; */
89 compile_gasket(ModeInfo *mi)
92 int points = MI_CYCLES(mi) ? MI_CYCLES(mi) : 9999;
95 /* define verticies */
97 vertex[0].y = -(1.0/3.0)*sqrt((2.0/3.0));
98 vertex[0].z = -sqrt(3.0)/6.0;
101 vertex[1].y = -(1.0/3.0)*sqrt((2.0/3.0));
102 vertex[1].z = -sqrt(3.0)/6.0;
105 vertex[2].y = (2.0/3.0)*sqrt((2.0/3.0));
106 vertex[2].z = -sqrt(3.0)/6.0;
110 vertex[3].z = sqrt(3.0)/3.0;
117 for( i = 0; i < points ; i++ )
120 vertex[4].x = ( vertex[4].x + vertex[p].x )/2.0;
121 vertex[4].y = ( vertex[4].y + vertex[p].y )/2.0;
122 vertex[4].z = ( vertex[4].z + vertex[p].z )/2.0;
124 glVertex4f( vertex[4].x, vertex[4].y, vertex[4].z, 1.0 );
132 gasketstruct *gp = &gasket[MI_SCREEN(mi)];
134 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
136 glLightfv(GL_LIGHT0, GL_AMBIENT, gp->light_colour);
137 glEnable(GL_LIGHTING);
139 glEnable(GL_DEPTH_TEST);
142 glTranslatef( gp->pos[0], gp->pos[1], gp->pos[2] );
145 glRotatef(2*gp->angle, 1.0, 0.0, 0.0);
146 glRotatef(3*gp->angle, 0.0, 1.0, 0.0);
147 glRotatef( gp->angle, 0.0, 0.0, 1.0);
148 glScalef( 8.0, 8.0, 8.0 );
149 glCallList(gp->gasket1);
158 /* new window size or exposure */
160 reshape(int width, int height)
162 GLfloat h = (GLfloat) height / (GLfloat) width;
164 glViewport(0, 0, (GLint) width, (GLint) height);
165 glMatrixMode(GL_PROJECTION);
168 gluPerspective( 30.0, 1/h, 1.0, 100.0 );
169 gluLookAt( 0.0, 0.0, 15.0,
172 glMatrixMode(GL_MODELVIEW);
174 glTranslatef(0.0, 0.0, -40.0);
176 /* The depth buffer will be cleared, if needed, before the
177 * next frame. Right now we just want to black the screen.
179 glClear(GL_COLOR_BUFFER_BIT);
185 gasketstruct *gp = &gasket[MI_SCREEN(mi)];
187 gp->xinc = 0.1*(1.0*random()/RAND_MAX);
188 gp->yinc = 0.1*(1.0*random()/RAND_MAX);
189 gp->zinc = 0.1*(1.0*random()/RAND_MAX);
190 gp->light_colour[0] = 6.0;
191 gp->light_colour[1] = 6.0;
192 gp->light_colour[2] = 6.0;
193 gp->light_colour[3] = 1.0;
197 /* draw the gasket */
198 gp->gasket1 = glGenLists(1);
199 glNewList(gp->gasket1, GL_COMPILE);
205 init_gasket(ModeInfo *mi)
207 int screen = MI_SCREEN(mi);
212 if ((gasket = (gasketstruct *) calloc(MI_NUM_SCREENS(mi),
213 sizeof (gasketstruct))) == NULL)
216 gp = &gasket[screen];
218 gp->window = MI_WINDOW(mi);
219 gp->view_rotx = NRAND(360);
220 gp->view_roty = NRAND(360);
221 gp->view_rotz = NRAND(360);
222 gp->angle = NRAND(360)/90.0;
224 if ((gp->glx_context = init_GL(mi)) != NULL)
226 reshape(MI_WIDTH(mi), MI_HEIGHT(mi));
236 draw_gasket(ModeInfo * mi)
238 gasketstruct *gp = &gasket[MI_SCREEN(mi)];
239 Display *display = MI_DISPLAY(mi);
240 Window window = MI_WINDOW(mi);
242 int rot_incr = 1;/*MI_COUNT(mi) ? MI_COUNT(mi) : 1;*/
244 if (!gp->glx_context) return;
246 glDrawBuffer(GL_BACK);
248 glXMakeCurrent(display, window, *(gp->glx_context));
251 /* do the colour change & movement thing */
252 gp->angle = (int) (gp->angle + angle_incr) % 360;
253 gp->light_colour[0] = 3.0*SINF(gp->angle/20.0) + 4.0;
254 gp->light_colour[1] = 3.0*SINF(gp->angle/30.0) + 4.0;
255 gp->light_colour[2] = 3.0*SINF(gp->angle/60.0) + 4.0;
256 if ( FABSF( gp->pos[0] ) > 9.0 ) gp->xinc = -1.0 * gp->xinc;
257 if ( FABSF( gp->pos[1] ) > 7.0 ) gp->yinc = -1.0 * gp->yinc;
258 if ( FABSF( gp->pos[2] ) >15.0 ) gp->zinc = -1.0 * gp->zinc;
259 gp->pos[0] += gp->xinc;
260 gp->pos[1] += gp->yinc;
261 gp->pos[2] += gp->zinc;
262 gp->view_rotx = (int) (gp->view_rotx + rot_incr) % 360;
263 gp->view_roty = (int) (gp->view_roty +(rot_incr/2.0)) % 360;
264 gp->view_rotz = (int) (gp->view_rotz +(rot_incr/3.0)) % 360;
267 glXSwapBuffers(display, window);
271 release_gasket(ModeInfo * mi)
277 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
279 gasketstruct *gp = &gasket[screen];
283 /* Display lists MUST be freed while their glXContext is current. */
284 glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context));
286 if (glIsList(gp->gasket1)) glDeleteLists(gp->gasket1, 1);
289 (void) free((void *) gasket);
296 /*********************************************************/