1: #line 3331 "./lpsrc/flx_sdl.pak"
2:
3: /*
4: * This code was created by Jeff Molofee '99
5: * (ported to Linux/SDL by Ti Leggett '01)
6: *
7: * If you've found this code useful, please let me know.
8: *
9: * Visit Jeff at http:
10: *
11: * or for port-specific comments, questions, bugreports etc.
12: * email to leggett@eecs.tulane.edu
13: */
14:
15:
16: include "SDL/SDL";
17: include "SDL/SDL_keyboard";
18: include "SDL/SDL_keysym";
19: include "SDL/SDL_video";
20: include "SDL/SDL_events";
21: include "SDL/SDL_timer";
22: include "SDL/SDL_mutex";
23: include "SDL/SDL_opengl";
24:
25: include "flx_faio";
26: include "flx_faio_sdl";
27:
28: open C_hack;
29: open Carray;
30: open MixedInt;
31: open Uint32;
32: open Uint8;
33: open Float;
34:
35: open SDL_h;
36: open SDL_video_h;
37: open SDL_keyboard_h;
38: open SDL_events_h;
39: open SDL_keysym_h;
40: open SDL_timer_h;
41: open SDL_mutex_h;
42:
43:
44: open SDL_events;
45:
46: open SDL_opengl_h;
47:
48: /* screen width, height, and bit depth */
49: val SCREEN_WIDTH = 640;
50: val SCREEN_HEIGHT = 480;
51: val SCREEN_BPP = 16;
52:
53: /* function to reset our viewport after a window resize */
54: proc resizeWindow( wwidth : int, hheight :int)
55: {
56: var height = hheight;
57: var width = wwidth;
58:
59: block_sdl_events event_lock;
60: /* Protect against a divide by zero */
61: if height == 0 do height = 1; done;
62: var ratio = double_of width / double_of height;
63:
64: /* Setup our viewport. */
65: glViewport( 0, 0, width, height );
66:
67: /* change to the projection matrix and set our viewing volume. */
68: glMatrixMode( GL_PROJECTION );
69: glLoadIdentity( );
70:
71: /* Set our perspective */
72: gluPerspective( 45.0, ratio, 0.1, 100.0 );
73:
74: /* Make sure we're chaning the model view and not the projection */
75: glMatrixMode( GL_MODELVIEW );
76:
77: /* Reset The View */
78: glLoadIdentity( );
79: unblock_sdl_events event_lock;
80: }
81:
82: /* general OpenGL initialization function */
83: proc initGL()
84: {
85: /* Enable smooth shading */
86: glShadeModel( GL_SMOOTH );
87:
88: /* Set the background black */
89: glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
90:
91: /* Depth buffer setup */
92: glClearDepth( 1.0 );
93:
94: /* Enables Depth Testing */
95: glEnable( GL_DEPTH_TEST );
96:
97: /* The Type Of Depth Test To Do */
98: glDepthFunc( GL_LEQUAL );
99:
100: /* Really Nice Perspective Calculations */
101: glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
102: }
103:
104: /* These are to calculate our fps */
105: var T0 = 0;
106: var Frames = 0;
107:
108: var rtri = 0.0f; /* Triangle Rotation ( NEW ) */
109: var rquad = 0.0f; /* Quad Rotation ( NEW ) */
110:
111: proc rotate()
112: {
113: /* Increase The Rotation Variable For The Triangle ( NEW ) */
114: rtri += 0.2f;
115: /* Decrease The Rotation Variable For The Quad ( NEW ) */
116: rquad -=0.15f;
117: }
118:
119: /* Here goes our drawing code */
120: proc drawGLScene(drawing:1->0)
121: {
122: block_sdl_events event_lock;
123: drawing();
124: unblock_sdl_events event_lock;
125:
126: /* Gather our frames per second */
127: Frames++;
128: {
129: var t = SDL_GetTicks();
130: if t - T0 >= 5000 do
131: val seconds = double_of (t - T0) / 1000.0;
132: val fps = double_of Frames / seconds;
133: print Frames; print " frames in "; print seconds;
134: print " seconds = "; print fps; print " FPS"; endl;
135: T0 = t;
136: Frames = 0;
137: done;
138: };
139: rotate();
140: }
141:
142: /* whether or not the window is active */
143: var isActive = true;
144:
145: if SDL_Init(SDL_INIT_AUDIO \| SDL_INIT_VIDEO) < 0 do
146: print "Unable to init SDL"; endl;
147: System::exit(1);
148: done;
149:
150: var event_lock = SDL_CreateMutex();
151:
152:
153: proc Quit(n:int)
154: {
155: SDL_Quit;
156: System::exit 0;
157: }
158:
159: /* Fetch the video info */
160: var videoInfo = SDL_GetVideoInfo();
161:
162: if isNULL videoInfo do
163: print "Video query failed"; endl;
164: Quit 1;
165: done;
166:
167: /* the flags to pass to SDL_SetVideoMode */
168: var
169: videoFlags = SDL_OPENGL; /* Enable OpenGL in SDL */
170: videoFlags |= cast[uint] SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
171: videoFlags |= SDL_HWPALETTE; /* Store the palette in hardware */
172: videoFlags |= SDL_RESIZABLE; /* Enable window resizing */
173:
174: /* This checks to see if surfaces can be stored in memory */
175: if videoInfo.->hw_available != 0 do
176: videoFlags |= SDL_HWSURFACE;
177: else
178: videoFlags |= SDL_SWSURFACE;
179: done;
180:
181: /* This checks if hardware blits can be done */
182: if videoInfo.->blit_hw != 0 do
183: videoFlags |= SDL_HWACCEL;
184: done;
185:
186: /* Sets up OpenGL double buffering */
187: ignore$ SDL_GL_SetAttribute( cast[SDL_GLattr] SDL_GL_DOUBLEBUFFER, 1 );
188:
189: /* get a SDL surface */
190: var surface = SDL_SetVideoMode
191: (SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, videoFlags )
192: ;
193:
194: /* Verify there is a surface */
195: if isNULL surface do
196: print "Video mode set failed"; endl;
197: Quit 1;
198: done;
199:
200: /* initialize OpenGL */
201: initGL();
202:
203: /* resize the initial window */
204: resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );
205:
206:
207: proc handle_active (e:SDL_ActiveEvent)
208: {
209: isActive = e.gain != 0;
210: }
211:
212: proc handle_resize(e:SDL_ResizeEvent)
213: {
214: block_sdl_events event_lock;
215: surface = SDL_SetVideoMode(
216: e.w,
217: e.h,
218: 16, videoFlags
219: );
220: if isNULL surface do
221: print "Could not get a surface after resize"; endl;
222: done;
223: resizeWindow( e.w, e.h );
224: unblock_sdl_events event_lock;
225: }
226:
227: /* function to handle key press events */
228: proc handle_key( keysym : SDL_keysym)
229: {
230: match keysym.sym with
231: | ?k when k == SDLK_ESCAPE => { Quit 0; }
232: | ?k when k == SDLK_F1 =>
233: {
234: block_sdl_events event_lock;
235: ignore$ SDL_WM_ToggleFullScreen( surface );
236: unblock_sdl_events event_lock;
237: }
238: | _ => {}
239: endmatch;
240: }
241:
242: /* draw the scene */
243: proc draw(drawing: 1->0) {
244: if isActive call drawGLScene( drawing );
245: }
246:
247: proc keychan(x:schannel[SDL_keysym])
248: {
249: whilst true do
250: var &k : SDL_keysym <- read x;
251: handle_key k;
252: done;
253: }
254:
255: proc activechan(x:schannel[SDL_ActiveEvent])
256: {
257: whilst true do
258: var &k : SDL_ActiveEvent <- read x;
259: handle_active k;
260: done;
261: }
262:
263: proc resizechan(x:schannel[SDL_ResizeEvent])
264: {
265: whilst true do
266: var &k : SDL_ResizeEvent <- read x;
267: handle_resize k;
268: done;
269: }
270:
271: proc drawchan(x:schannel[int], drawing:1->0)
272: {
273: whilst true do
274: var &k : int <- read x;
275: draw drawing;
276: done;
277: }
278:
279: proc execute(x:schannel[int], something:1->0)
280: {
281: whilst true do
282: var &k : int <- read x;
283: something();
284: done;
285: }
286:
287: val clock = Faio::mk_alarm_clock();
288: proc poll_event(e: &SDL_Event)
289: {
290: tryagain:>
291:
292: var result = SDL_PollEvent(unref e);
293: if result > 0 do
294:
295: return;
296: done;
297: Faio::sleep$ clock, 0.1;
298: goto tryagain;
299: }
300:
301: proc dispatch_event(
302: keyboard:schannel[SDL_keysym],
303: active:schannel[SDL_ActiveEvent],
304: resize:schannel[SDL_ResizeEvent]
305: )
306: {
307: whilst true do
308:
309: var e : SDL_Event;
310: poll_event(&e);
311: match e.type_ with
312: | ?et when et == SDL_ACTIVEEVENT =>
313: { write (active, e.active); }
314:
315: | ?et when et == SDL_VIDEORESIZE =>
316: { write (resize, e.resize); }
317:
318: | ?et when et == SDL_KEYDOWN =>
319: { write (keyboard, e.key.keysym); }
320:
321: | ?et when et == SDL_QUIT =>
322: { Quit 0; }
323:
324: | _ => {}
325: endmatch;
326: done;
327: }
328:
329: /* write ticks at the desired framerate */
330: proc framerate (x:schannel[int], framerate:double)
331: {
332: whilst true do
333: Faio::sleep $ clock,framerate;
334: write (x,1);
335: done;
336: }
337:
338: /* LINEAR CONTROL MODEL: CANNOT DEADLOCK
339: ~~> async/sync connection
340: --> sync/sync connection
341:
342: SDL_event ~~> dispatcher
343: --> resize handler
344: --> active handler
345: --> key handler
346: timer ~~> framerate --> draw
347: */
348:
349: /* make our communication channels */
350: var keyboard = mk_schannel[SDL_keysym] ();
351: var active = mk_schannel[SDL_ActiveEvent] ();
352: var resize = mk_schannel[SDL_ResizeEvent] ();
353: var clicks = mk_schannel[int] ();
354: var rotation = mk_schannel[int] ();
355:
356: /* start up the fthreads and plug them together */
357: spawn_fthread { dispatch_event (keyboard, active, resize); };
358: spawn_fthread { resizechan resize; };
359: spawn_fthread { activechan active; };
360: spawn_fthread { keychan keyboard; };
361:
362: spawn_fthread { drawchan (clicks, the Drawing); };
363: spawn_fthread { framerate (clicks, 0.05); };
364: spawn_fthread { execute (rotation, the rotate); };
365: spawn_fthread { framerate (rotation, 0.1); };
366:
367:
368:
369: /* Here goes our drawing code */
370: proc Drawing()
371: {
372: /* Clear The Screen And The Depth Buffer */
373: glClear( GL_COLOR_BUFFER_BIT \| GL_DEPTH_BUFFER_BIT );
374:
375: /* Move Left 1.5 Units And Into The Screen 6.0 */
376: glLoadIdentity();
377: glTranslatef( -1.5f, 0.0f, -6.0f );
378:
379: /* Rotate The Triangle On The Y axis ( NEW ) */
380: glRotatef( rtri, 0.0f, 1.0f, 0.0f );
381:
382: glBegin( GL_TRIANGLES ); /* Drawing Using Triangles */
383: glColor3f( 1.0f, 0.0f, 0.0f ); /* Red */
384: glVertex3f( 0.0f, 1.0f, 0.0f ); /* Top Of Triangle (Front) */
385: glColor3f( 0.0f, 1.0f, 0.0f ); /* Green */
386: glVertex3f( -1.0f, -1.0f, 1.0f ); /* Left Of Triangle (Front) */
387: glColor3f( 0.0f, 0.0f, 1.0f ); /* Blue */
388: glVertex3f( 1.0f, -1.0f, 1.0f ); /* Right Of Triangle (Front) */
389:
390: glColor3f( 1.0f, 0.0f, 0.0f ); /* Red */
391: glVertex3f( 0.0f, 1.0f, 0.0f ); /* Top Of Triangle (Right) */
392: glColor3f( 0.0f, 0.0f, 1.0f ); /* Blue */
393: glVertex3f( 1.0f, -1.0f, 1.0f ); /* Left Of Triangle (Right) */
394: glColor3f( 0.0f, 1.0f, 0.0f ); /* Green */
395: glVertex3f( 1.0f, -1.0f, -1.0f ); /* Right Of Triangle (Right) */
396:
397: glColor3f( 1.0f, 0.0f, 0.0f ); /* Red */
398: glVertex3f( 0.0f, 1.0f, 0.0f ); /* Top Of Triangle (Back) */
399: glColor3f( 0.0f, 1.0f, 0.0f ); /* Green */
400: glVertex3f( 1.0f, -1.0f, -1.0f ); /* Left Of Triangle (Back) */
401: glColor3f( 0.0f, 0.0f, 1.0f ); /* Blue */
402: glVertex3f( -1.0f, -1.0f, -1.0f ); /* Right Of Triangle (Back) */
403:
404: glColor3f( 1.0f, 0.0f, 0.0f ); /* Red */
405: glVertex3f( 0.0f, 1.0f, 0.0f ); /* Top Of Triangle (Left) */
406: glColor3f( 0.0f, 0.0f, 1.0f ); /* Blue */
407: glVertex3f( -1.0f, -1.0f, -1.0f ); /* Left Of Triangle (Left) */
408: glColor3f( 0.0f, 1.0f, 0.0f ); /* Green */
409: glVertex3f( -1.0f, -1.0f, 1.0f ); /* Right Of Triangle (Left) */
410: glEnd( ); /* Finished Drawing The Triangle */
411:
412: /* Move Right 3 Units */
413: glLoadIdentity( );
414: glTranslatef( 1.5f, 0.0f, -6.0f );
415:
416: /* Rotate The Quad On The X axis ( NEW ) */
417: glRotatef( rquad, 1.0f, 0.0f, 0.0f );
418:
419: /* Set The Color To Blue One Time Only */
420: glColor3f( 0.5f, 0.5f, 1.0f);
421:
422: glBegin( GL_QUADS ); /* Draw A Quad */
423: glColor3f( 0.0f, 1.0f, 0.0f ); /* Set The Color To Green */
424: glVertex3f( 1.0f, 1.0f, -1.0f ); /* Top Right Of The Quad (Top) */
425: glVertex3f( -1.0f, 1.0f, -1.0f ); /* Top Left Of The Quad (Top) */
426: glVertex3f( -1.0f, 1.0f, 1.0f ); /* Bottom Left Of The Quad (Top) */
427: glVertex3f( 1.0f, 1.0f, 1.0f ); /* Bottom Right Of The Quad (Top) */
428:
429: glColor3f( 1.0f, 0.5f, 0.0f ); /* Set The Color To Orange */
430: glVertex3f( 1.0f, -1.0f, 1.0f ); /* Top Right Of The Quad (Botm) */
431: glVertex3f( -1.0f, -1.0f, 1.0f ); /* Top Left Of The Quad (Botm) */
432: glVertex3f( -1.0f, -1.0f, -1.0f ); /* Bottom Left Of The Quad (Botm) */
433: glVertex3f( 1.0f, -1.0f, -1.0f ); /* Bottom Right Of The Quad (Botm) */
434:
435: glColor3f( 1.0f, 0.0f, 0.0f ); /* Set The Color To Red */
436: glVertex3f( 1.0f, 1.0f, 1.0f ); /* Top Right Of The Quad (Front) */
437: glVertex3f( -1.0f, 1.0f, 1.0f ); /* Top Left Of The Quad (Front) */
438: glVertex3f( -1.0f, -1.0f, 1.0f ); /* Bottom Left Of The Quad (Front) */
439: glVertex3f( 1.0f, -1.0f, 1.0f ); /* Bottom Right Of The Quad (Front) */
440:
441: glColor3f( 1.0f, 1.0f, 0.0f ); /* Set The Color To Yellow */
442: glVertex3f( 1.0f, -1.0f, -1.0f ); /* Bottom Left Of The Quad (Back) */
443: glVertex3f( -1.0f, -1.0f, -1.0f ); /* Bottom Right Of The Quad (Back) */
444: glVertex3f( -1.0f, 1.0f, -1.0f ); /* Top Right Of The Quad (Back) */
445: glVertex3f( 1.0f, 1.0f, -1.0f ); /* Top Left Of The Quad (Back) */
446:
447: glColor3f( 0.0f, 0.0f, 1.0f ); /* Set The Color To Blue */
448: glVertex3f( -1.0f, 1.0f, 1.0f ); /* Top Right Of The Quad (Left) */
449: glVertex3f( -1.0f, 1.0f, -1.0f ); /* Top Left Of The Quad (Left) */
450: glVertex3f( -1.0f, -1.0f, -1.0f ); /* Bottom Left Of The Quad (Left) */
451: glVertex3f( -1.0f, -1.0f, 1.0f ); /* Bottom Right Of The Quad (Left) */
452:
453: glColor3f( 1.0f, 0.0f, 1.0f ); /* Set The Color To Violet */
454: glVertex3f( 1.0f, 1.0f, -1.0f ); /* Top Right Of The Quad (Right) */
455: glVertex3f( 1.0f, 1.0f, 1.0f ); /* Top Left Of The Quad (Right) */
456: glVertex3f( 1.0f, -1.0f, 1.0f ); /* Bottom Left Of The Quad (Right) */
457: glVertex3f( 1.0f, -1.0f, -1.0f ); /* Bottom Right Of The Quad (Right) */
458: glEnd( ); /* Done Drawing The Quad */
459:
460: /* Draw it to the screen */
461: SDL_GL_SwapBuffers( );
462: }