1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* invert --- shere inversion */
3 
4 #if 0
5 static const char sccsid[] = "@(#)invert.c	5.01 2001/03/01 xlockmore";
6 #endif
7 
8 /*-
9  * invert.c - Sphere inversion
10  *
11  * See xlock.c for copying information.
12  *
13  * Revision History:
14  * 01-Nov-2000: Allocation checks
15  * 199?: Written
16  *
17  * Tim Rowley (code from the Geometry Center <URL:http://www.geom.umn.edu/>
18  *
19  * This is a sphere eversion of William P. Thurston which was the subject
20  * of the Geometry Center film "Outside In".  The code is based on the
21  * software which was used to create the RIB files for the film.
22  * Trying to figure it out from the full eversion is difficult.  If you get
23  * a chance to look at the original film, it leads up the eversion nicely.
24  * There is more information about the eversion, including the script from
25  * the film, at: http://www.geom.umn.edu/docs/outreach/oi/
26  *
27  * Demonstration of turning a sphere inside out without creating
28  * any kinks (two surfaces can occupy the same space at the same time).
29  *
30  * Revision History:
31  * 01-Mar-2001: Added FPS stuff E.Lassauge <lassauge AT users.sourceforge.net>
32  */
33 
34 #ifdef VMS
35 #include <types.h>
36 #endif
37 
38 #ifdef STANDALONE
39 #define MODE_invert
40 #define DEFAULTS	"*delay:	10000   \n"	\
41 			"*showFps:      False   \n"     \
42 			"*wireframe:	False	\n"
43 
44 #define invert_handle_event 0
45 #define free_invert 0
46 #define reshape_invert 0
47 #include "xlockmore.h"
48 #else /* !STANDALONE */
49 #include "xlock.h"
50 #include "visgl.h"
51 #endif /* !STANDALONE */
52 
53 #ifdef MODE_invert
54 
55 #include "i_linkage.h"
56 #define STEPS 75
57 
58 ENTRYPOINT ModeSpecOpt invert_opts =
59 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
60 
61 #ifdef USE_MODULES
62 ModStruct invert_description =
63 {(char *) "invert", (char *) "init_invert",
64  (char *) "draw_invert", (char *) "release_invert",
65  (char *) "draw_invert", (char *) "init_invert",
66  (char *) NULL, &invert_opts,
67  80000, 1, 1, 1, 64, 1.0, (char *) "",
68  (char *) "Shows a sphere inverted without wrinkles", 0, NULL};
69 
70 #endif
71 
72 
73 static spherestruct *spheres = (spherestruct *) NULL;
74 
75 /* new window size or exposure */
76 static void
reshape(int width,int height)77 reshape(int width, int height)
78 {
79   GLfloat     h = (GLfloat) height / (GLfloat) width;
80 
81   glViewport(0, 0, (GLint) width, (GLint) height);
82   glMatrixMode(GL_PROJECTION);
83   glLoadIdentity();
84   glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
85   glMatrixMode(GL_MODELVIEW);
86   glLoadIdentity();
87   glTranslatef(0.0, 0.0, -10.0);
88 
89   /* The depth buffer will be cleared, if needed, before the
90    * next frame.  Right now we just want to black the screen.
91    */
92   glClear(GL_COLOR_BUFFER_BIT);
93 }
94 
95 
96 static void
pinit(void)97 pinit(void)
98 {
99 /*
100   GLfloat front_mat[] = {.8, .7, .4, 1.0};
101   GLfloat back_mat[] = {.508, .333, .774, 1.0};
102   */
103 
104   GLfloat front_ambient[] = {.16, .14, .08, 1.0};
105   GLfloat front_diffuse[] = {.56, .49, .28, 1.0};
106   GLfloat front_specular[] = {1, 1, 0.8, 1.0};
107 
108   GLfloat back_ambient[] = {.1016, .0666, .1548, 1.0};
109   GLfloat back_diffuse[] = {.254, .166, .387, 1.0};
110   GLfloat back_specular[] = {.4, .2, .5, 1.0};
111 
112   /* spherestruct *gp = &spheres[MI_SCREEN(mi)]; */
113   static GLfloat pos[4] =
114   {5.0, 5.0, 10.0, 0.0};
115 
116   glLightfv(GL_LIGHT0, GL_POSITION, pos);
117   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
118   glEnable(GL_LIGHTING);
119   glEnable(GL_LIGHT0);
120   glEnable(GL_DEPTH_TEST);
121   glShadeModel(GL_SMOOTH);
122 
123   glMaterialfv(GL_FRONT, GL_AMBIENT, front_ambient);
124   glMaterialfv(GL_FRONT, GL_DIFFUSE, front_diffuse);
125   glMaterialfv(GL_FRONT, GL_SPECULAR, front_specular);
126   glMaterialf(GL_FRONT, GL_SHININESS, 32.0);
127 
128   glMaterialfv(GL_BACK, GL_AMBIENT, back_ambient);
129   glMaterialfv(GL_BACK, GL_DIFFUSE, back_diffuse);
130   glMaterialfv(GL_BACK, GL_SPECULAR, back_specular);
131   glMaterialf(GL_BACK, GL_SHININESS, 38.0);
132 }
133 
134 static void
free_invert_screen(Display * display,spherestruct * gp)135 free_invert_screen(Display *display, spherestruct *gp)
136 {
137   if (gp == NULL) {
138     return;
139   }
140   if (gp->glx_context) {
141     /* Display lists MUST be freed while their glXContext is current. */
142 #ifdef WIN32
143     wglMakeCurrent(hdc, gp->glx_context);
144 #else
145     glXMakeCurrent(display, gp->window, *(gp->glx_context));
146 #endif
147     if (glIsList(gp->frames)) {
148       glDeleteLists(gp->frames, STEPS);
149       gp->frames = 0;
150       /* Don't destroy the glXContext.  init_GL does that. */
151     }
152   }
153   if (gp->partlist != NULL) {
154     free(gp->partlist);
155     gp->partlist = (char *) NULL;
156   }
157   gp = NULL;
158 }
159 
160 ENTRYPOINT void
init_invert(ModeInfo * mi)161 init_invert(ModeInfo * mi)
162 {
163   spherestruct *gp;
164 
165   MI_INIT(mi, spheres);
166   gp = &spheres[MI_SCREEN(mi)];
167   gp->window = MI_WINDOW(mi);
168 
169   gp->time = 0;
170   gp->construction = 1;
171   gp->partlist = (char *) NULL;
172   gp->numsteps = STEPS;
173   gp->view_rotx = NRAND(360);
174   gp->view_roty = NRAND(360);
175   gp->view_rotz = NRAND(360);
176   if ((gp->glx_context = init_GL(mi)) != NULL) {
177     if ((gp->frames = glGenLists(STEPS)) == 0) {
178       free_invert_screen(MI_DISPLAY(mi), gp);
179       return;
180     }
181     reshape(MI_WIDTH(mi), MI_HEIGHT(mi));
182     pinit();
183   } else {
184     MI_CLEARWINDOW(mi);
185   }
186 }
187 
188 ENTRYPOINT void
draw_invert(ModeInfo * mi)189 draw_invert(ModeInfo * mi)
190 {
191   Display    *display = MI_DISPLAY(mi);
192   Window      window = MI_WINDOW(mi);
193   /* int         angle_incr = MI_CYCLES(mi) ? MI_CYCLES(mi) : 2; */
194   int         rot_incr = MI_COUNT(mi) ? MI_COUNT(mi) : 1;
195   spherestruct *gp;
196 
197   if (spheres == NULL)
198  	return;
199   gp = &spheres[MI_SCREEN(mi)];
200 
201   if (!gp->glx_context)
202     return;
203 
204   MI_IS_DRAWN(mi) = True;
205 
206   glDrawBuffer(GL_BACK);
207 #ifdef WIN32
208    wglMakeCurrent(hdc, gp->glx_context);
209 #else
210    glXMakeCurrent(display, window, *(gp->glx_context));
211 #endif
212   if (!invert_draw(gp)) {
213     free_invert_screen(display, gp);
214     return;
215   }
216 
217   /* let's do something so we don't get bored */
218   if (gp->time == STEPS-1)
219     gp->construction = 0;
220   if (gp->time == STEPS-1)
221     gp->forwards = 0;
222   if (gp->time == 0)
223     gp->forwards = 1;
224   if (gp->forwards)
225     gp->time++;
226   else
227     gp->time--;
228   gp->view_rotx = (int) (gp->view_rotx + rot_incr) % 360;
229   gp->view_roty = (int) (gp->view_roty + rot_incr) % 360;
230   gp->view_rotz = (int) (gp->view_rotz + rot_incr) % 360;
231 
232   glFinish();
233   if (MI_IS_FPS(mi)) do_fps (mi);
234   glXSwapBuffers(display, window);
235 }
236 
237 ENTRYPOINT void
release_invert(ModeInfo * mi)238 release_invert(ModeInfo * mi)
239 {
240   if (spheres != NULL) {
241     int         screen;
242 
243     for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
244        free_invert_screen(MI_DISPLAY(mi), &spheres[screen]);
245     free(spheres);
246     spheres = (spherestruct *) NULL;
247   }
248   FreeAllGL(mi);
249 }
250 
251 XSCREENSAVER_MODULE ("Invert", invert)
252 
253 #endif /* MODE_invert */
254