ruby-glfw 0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (206) hide show
  1. data/README +1 -0
  2. data/README.API +73 -0
  3. data/Rakefile +120 -0
  4. data/examples/boing.rb +519 -0
  5. data/examples/gears.rb +327 -0
  6. data/examples/keytest.rb +117 -0
  7. data/examples/listmodes.rb +20 -0
  8. data/examples/mipmaps.rb +104 -0
  9. data/examples/mipmaps.tga +0 -0
  10. data/examples/particles.rb +837 -0
  11. data/examples/pong3d.rb +741 -0
  12. data/examples/pong3d_field.tga +0 -0
  13. data/examples/pong3d_instr.tga +0 -0
  14. data/examples/pong3d_menu.tga +0 -0
  15. data/examples/pong3d_title.tga +0 -0
  16. data/examples/pong3d_winner1.tga +0 -0
  17. data/examples/pong3d_winner2.tga +0 -0
  18. data/examples/splitview.rb +432 -0
  19. data/examples/triangle.rb +89 -0
  20. data/examples/wave.rb +294 -0
  21. data/ext/glfw/glfw.c +1094 -0
  22. data/ext/glfw/mkrf_conf.rb +70 -0
  23. data/glfw-src/Makefile +220 -0
  24. data/glfw-src/compile.ami +61 -0
  25. data/glfw-src/compile.bat +217 -0
  26. data/glfw-src/compile.sh +607 -0
  27. data/glfw-src/docs/Makefile +57 -0
  28. data/glfw-src/docs/Reference.pdf +0 -0
  29. data/glfw-src/docs/UsersGuide.pdf +0 -0
  30. data/glfw-src/docs/cleanup.bat +22 -0
  31. data/glfw-src/docs/glfwdoc.sty +80 -0
  32. data/glfw-src/docs/glfwrm.tex +3034 -0
  33. data/glfw-src/docs/glfwug.tex +2024 -0
  34. data/glfw-src/docs/readme.txt +80 -0
  35. data/glfw-src/examples/Makefile.amigaos.gcc +70 -0
  36. data/glfw-src/examples/Makefile.amigaos.vbcc +70 -0
  37. data/glfw-src/examples/Makefile.dos.djgpp +71 -0
  38. data/glfw-src/examples/Makefile.macosx.gcc +96 -0
  39. data/glfw-src/examples/Makefile.win32.bcc +75 -0
  40. data/glfw-src/examples/Makefile.win32.cross-mgw +79 -0
  41. data/glfw-src/examples/Makefile.win32.cygwin +79 -0
  42. data/glfw-src/examples/Makefile.win32.lcc +74 -0
  43. data/glfw-src/examples/Makefile.win32.mgw +75 -0
  44. data/glfw-src/examples/Makefile.win32.msvc +74 -0
  45. data/glfw-src/examples/Makefile.win32.ow +74 -0
  46. data/glfw-src/examples/Makefile.win32.pellesc +74 -0
  47. data/glfw-src/examples/Makefile.x11.in +54 -0
  48. data/glfw-src/examples/boing.c +606 -0
  49. data/glfw-src/examples/bundle.sh +46 -0
  50. data/glfw-src/examples/gears.c +382 -0
  51. data/glfw-src/examples/keytest.c +264 -0
  52. data/glfw-src/examples/listmodes.c +48 -0
  53. data/glfw-src/examples/mipmaps.c +126 -0
  54. data/glfw-src/examples/mipmaps.tga +0 -0
  55. data/glfw-src/examples/mtbench.c +301 -0
  56. data/glfw-src/examples/mthello.c +48 -0
  57. data/glfw-src/examples/particles.c +1148 -0
  58. data/glfw-src/examples/pong3d.c +839 -0
  59. data/glfw-src/examples/pong3d_field.tga +0 -0
  60. data/glfw-src/examples/pong3d_instr.tga +0 -0
  61. data/glfw-src/examples/pong3d_menu.tga +0 -0
  62. data/glfw-src/examples/pong3d_title.tga +0 -0
  63. data/glfw-src/examples/pong3d_winner1.tga +0 -0
  64. data/glfw-src/examples/pong3d_winner2.tga +0 -0
  65. data/glfw-src/examples/splitview.c +506 -0
  66. data/glfw-src/examples/triangle.c +108 -0
  67. data/glfw-src/examples/wave.c +397 -0
  68. data/glfw-src/images/opengl.gif +0 -0
  69. data/glfw-src/images/osicert.gif +0 -0
  70. data/glfw-src/include/GL/glfw.h +486 -0
  71. data/glfw-src/lib/amigaos/Makefile.amigaos.gcc +128 -0
  72. data/glfw-src/lib/amigaos/Makefile.amigaos.vbcc +128 -0
  73. data/glfw-src/lib/amigaos/SDI_compiler.h +94 -0
  74. data/glfw-src/lib/amigaos/amigaos_enable.c +51 -0
  75. data/glfw-src/lib/amigaos/amigaos_fullscreen.c +319 -0
  76. data/glfw-src/lib/amigaos/amigaos_glext.c +61 -0
  77. data/glfw-src/lib/amigaos/amigaos_init.c +284 -0
  78. data/glfw-src/lib/amigaos/amigaos_joystick.c +359 -0
  79. data/glfw-src/lib/amigaos/amigaos_thread.c +494 -0
  80. data/glfw-src/lib/amigaos/amigaos_time.c +206 -0
  81. data/glfw-src/lib/amigaos/amigaos_window.c +830 -0
  82. data/glfw-src/lib/amigaos/platform.h +337 -0
  83. data/glfw-src/lib/dos/Makefile.dos.djgpp +146 -0
  84. data/glfw-src/lib/dos/dos_enable.c +51 -0
  85. data/glfw-src/lib/dos/dos_events.c +173 -0
  86. data/glfw-src/lib/dos/dos_fullscreen.c +101 -0
  87. data/glfw-src/lib/dos/dos_glext.c +59 -0
  88. data/glfw-src/lib/dos/dos_init.c +105 -0
  89. data/glfw-src/lib/dos/dos_irq.s +246 -0
  90. data/glfw-src/lib/dos/dos_joystick.c +94 -0
  91. data/glfw-src/lib/dos/dos_keyboard.c +694 -0
  92. data/glfw-src/lib/dos/dos_mouse.c +337 -0
  93. data/glfw-src/lib/dos/dos_thread.c +267 -0
  94. data/glfw-src/lib/dos/dos_time.c +309 -0
  95. data/glfw-src/lib/dos/dos_window.c +563 -0
  96. data/glfw-src/lib/dos/platform.h +341 -0
  97. data/glfw-src/lib/enable.c +295 -0
  98. data/glfw-src/lib/fullscreen.c +95 -0
  99. data/glfw-src/lib/glext.c +201 -0
  100. data/glfw-src/lib/image.c +629 -0
  101. data/glfw-src/lib/init.c +108 -0
  102. data/glfw-src/lib/input.c +280 -0
  103. data/glfw-src/lib/internal.h +210 -0
  104. data/glfw-src/lib/joystick.c +101 -0
  105. data/glfw-src/lib/macosx/Makefile.macosx.gcc +172 -0
  106. data/glfw-src/lib/macosx/Makefile.macosx.gcc.universal +166 -0
  107. data/glfw-src/lib/macosx/libglfw.pc.in +11 -0
  108. data/glfw-src/lib/macosx/macosx_enable.c +42 -0
  109. data/glfw-src/lib/macosx/macosx_fullscreen.c +126 -0
  110. data/glfw-src/lib/macosx/macosx_glext.c +52 -0
  111. data/glfw-src/lib/macosx/macosx_init.c +194 -0
  112. data/glfw-src/lib/macosx/macosx_joystick.c +50 -0
  113. data/glfw-src/lib/macosx/macosx_thread.c +414 -0
  114. data/glfw-src/lib/macosx/macosx_time.c +112 -0
  115. data/glfw-src/lib/macosx/macosx_window.c +1279 -0
  116. data/glfw-src/lib/macosx/platform.h +349 -0
  117. data/glfw-src/lib/stream.c +194 -0
  118. data/glfw-src/lib/tga.c +405 -0
  119. data/glfw-src/lib/thread.c +340 -0
  120. data/glfw-src/lib/time.c +83 -0
  121. data/glfw-src/lib/win32/Makefile.win32.bcc +265 -0
  122. data/glfw-src/lib/win32/Makefile.win32.cross-mgw +274 -0
  123. data/glfw-src/lib/win32/Makefile.win32.cygwin +279 -0
  124. data/glfw-src/lib/win32/Makefile.win32.lcc +246 -0
  125. data/glfw-src/lib/win32/Makefile.win32.mgw +243 -0
  126. data/glfw-src/lib/win32/Makefile.win32.msvc +242 -0
  127. data/glfw-src/lib/win32/Makefile.win32.ow +242 -0
  128. data/glfw-src/lib/win32/Makefile.win32.pellesc +242 -0
  129. data/glfw-src/lib/win32/glfwdll.def +67 -0
  130. data/glfw-src/lib/win32/glfwdll_mgw1.def +67 -0
  131. data/glfw-src/lib/win32/glfwdll_mgw2.def +67 -0
  132. data/glfw-src/lib/win32/glfwdll_pellesc.def +65 -0
  133. data/glfw-src/lib/win32/libglfw.pc.in +11 -0
  134. data/glfw-src/lib/win32/platform.h +474 -0
  135. data/glfw-src/lib/win32/win32_dllmain.c +60 -0
  136. data/glfw-src/lib/win32/win32_enable.c +155 -0
  137. data/glfw-src/lib/win32/win32_fullscreen.c +317 -0
  138. data/glfw-src/lib/win32/win32_glext.c +85 -0
  139. data/glfw-src/lib/win32/win32_init.c +356 -0
  140. data/glfw-src/lib/win32/win32_joystick.c +234 -0
  141. data/glfw-src/lib/win32/win32_thread.c +511 -0
  142. data/glfw-src/lib/win32/win32_time.c +146 -0
  143. data/glfw-src/lib/win32/win32_window.c +1714 -0
  144. data/glfw-src/lib/window.c +727 -0
  145. data/glfw-src/lib/x11/Makefile.x11.in +243 -0
  146. data/glfw-src/lib/x11/platform.h +415 -0
  147. data/glfw-src/lib/x11/x11_enable.c +51 -0
  148. data/glfw-src/lib/x11/x11_fullscreen.c +524 -0
  149. data/glfw-src/lib/x11/x11_glext.c +69 -0
  150. data/glfw-src/lib/x11/x11_init.c +275 -0
  151. data/glfw-src/lib/x11/x11_joystick.c +371 -0
  152. data/glfw-src/lib/x11/x11_keysym2unicode.c +902 -0
  153. data/glfw-src/lib/x11/x11_thread.c +507 -0
  154. data/glfw-src/lib/x11/x11_time.c +154 -0
  155. data/glfw-src/lib/x11/x11_window.c +1746 -0
  156. data/glfw-src/license.txt +21 -0
  157. data/glfw-src/readme.html +927 -0
  158. data/glfw-src/support/d/examples/Makefile +59 -0
  159. data/glfw-src/support/d/examples/boing.d +610 -0
  160. data/glfw-src/support/d/examples/gears.d +379 -0
  161. data/glfw-src/support/d/examples/keytest.d +272 -0
  162. data/glfw-src/support/d/examples/listmodes.d +48 -0
  163. data/glfw-src/support/d/examples/mipmaps.d +126 -0
  164. data/glfw-src/support/d/examples/mtbench.d +304 -0
  165. data/glfw-src/support/d/examples/mthello.d +54 -0
  166. data/glfw-src/support/d/examples/particles.d +1150 -0
  167. data/glfw-src/support/d/examples/pong3d.d +840 -0
  168. data/glfw-src/support/d/examples/splitview.d +486 -0
  169. data/glfw-src/support/d/examples/triangle.d +108 -0
  170. data/glfw-src/support/d/examples/wave.d +400 -0
  171. data/glfw-src/support/d/imports/gl.d +4539 -0
  172. data/glfw-src/support/d/imports/glfw.d +349 -0
  173. data/glfw-src/support/d/imports/glu.d +328 -0
  174. data/glfw-src/support/d/lib/glfwdll.def +64 -0
  175. data/glfw-src/support/d/lib/glu32.def +56 -0
  176. data/glfw-src/support/d/lib/makefile +12 -0
  177. data/glfw-src/support/d/lib/opengl32.def +372 -0
  178. data/glfw-src/support/d/readme.html +83 -0
  179. data/glfw-src/support/delphi/examples/Triangle.dpr +105 -0
  180. data/glfw-src/support/delphi/lib/glfw.pas +437 -0
  181. data/glfw-src/support/delphi/readme.html +97 -0
  182. data/glfw-src/support/lua/examples/gears.lua +383 -0
  183. data/glfw-src/support/lua/examples/test1.lua +68 -0
  184. data/glfw-src/support/lua/readme.html +128 -0
  185. data/glfw-src/support/lua/src/luaglfw.c +1179 -0
  186. data/glfw-src/support/lua/src/luaglfw.h +48 -0
  187. data/glfw-src/support/lua/src/runlua.c +82 -0
  188. data/glfw-src/support/masm/examples/fpc.mac +47 -0
  189. data/glfw-src/support/masm/examples/makeit.bat +66 -0
  190. data/glfw-src/support/masm/examples/triangle.asm +232 -0
  191. data/glfw-src/support/masm/include/glfw.inc +326 -0
  192. data/glfw-src/support/masm/include/glu32.inc +55 -0
  193. data/glfw-src/support/masm/include/opengl32.inc +372 -0
  194. data/glfw-src/support/masm/lib/glfwdll.lib +0 -0
  195. data/glfw-src/support/masm/readme.html +170 -0
  196. data/glfw-src/support/msvc80/GLFW.sln +26 -0
  197. data/glfw-src/support/msvc80/GLFW.vcproj +257 -0
  198. data/glfw-src/support/msvc80/GLFWDLL.vcproj +287 -0
  199. data/glfw-src/support/visualbasic/bindings/glfw.bas +320 -0
  200. data/glfw-src/support/visualbasic/bindings/glu32.bas +284 -0
  201. data/glfw-src/support/visualbasic/bindings/opengl32.bas +999 -0
  202. data/glfw-src/support/visualbasic/examples/Triangle.bas +101 -0
  203. data/glfw-src/support/visualbasic/readme.html +164 -0
  204. data/website/index.html +84 -0
  205. data/website/style.css +110 -0
  206. metadata +301 -0
@@ -0,0 +1,104 @@
1
+ #========================================================================
2
+ # This is a small test application for GLFW.
3
+ # The program shows texture loading with mipmap generation and trilienar
4
+ # filtering.
5
+ # Note: For OpenGL 1.0 compability, we do not use texture objects (this
6
+ # is no issue, since we only have one texture).
7
+ #========================================================================
8
+ # Converted to ruby from GLFW example mipmaps.c
9
+
10
+ require 'opengl'
11
+ require 'glfw'
12
+ include Gl,Glu,Glfw
13
+
14
+ # Open OpenGL window
15
+ if( glfwOpenWindow( 640, 480, 0,0,0,0, 0,0, GLFW_WINDOW ) == false )
16
+ exit
17
+ end
18
+
19
+ # Enable sticky keys
20
+ glfwEnable( GLFW_STICKY_KEYS )
21
+
22
+ # Disable vertical sync (on cards that support it)
23
+ glfwSwapInterval( 0 )
24
+
25
+ # Load texture from file, and build all mipmap levels. The
26
+ # texture is automatically uploaded to texture memory.
27
+ if( glfwLoadTexture2D( "mipmaps.tga", GLFW_BUILD_MIPMAPS_BIT ) == false )
28
+ exit
29
+ end
30
+
31
+
32
+ # Use trilinear interpolation (GL_LINEAR_MIPMAP_LINEAR)
33
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
34
+ GL_LINEAR_MIPMAP_LINEAR )
35
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
36
+ GL_LINEAR )
37
+
38
+ # Enable texturing
39
+ glEnable( GL_TEXTURE_2D )
40
+
41
+ # Main loop
42
+ running = true
43
+ frames = 0
44
+ t0 = glfwGetTime()
45
+
46
+ while running
47
+ # Get time and mouse position
48
+ t = glfwGetTime()
49
+ x,y = glfwGetMousePos()
50
+
51
+ # Calculate and display FPS (frames per second)
52
+ if( (t-t0) > 1.0 || frames == 0 )
53
+ fps = frames.to_f / (t-t0)
54
+ titlestr = sprintf("Trilinear interpolation (%.1f FPS)", fps )
55
+ glfwSetWindowTitle( titlestr )
56
+ t0 = t
57
+ frames = 0
58
+ end
59
+ frames += 1
60
+
61
+ # Get window size (may be different than the requested size)
62
+ width,height = glfwGetWindowSize()
63
+ height = height > 0 ? height : 1
64
+
65
+ # Set viewport
66
+ glViewport( 0, 0, width, height )
67
+
68
+ # Clear color buffer
69
+ glClearColor( 0.0, 0.0, 0.0, 0.0 )
70
+ glClear( GL_COLOR_BUFFER_BIT )
71
+
72
+ # Select and setup the projection matrix
73
+ glMatrixMode( GL_PROJECTION )
74
+ glLoadIdentity()
75
+ gluPerspective( 65.0, width.to_f/height.to_f, 1.0, 50.0 )
76
+
77
+ # Select and setup the modelview matrix
78
+ glMatrixMode( GL_MODELVIEW )
79
+ glLoadIdentity()
80
+ gluLookAt( 0.0, 3.0, -20.0, # Eye-position
81
+ 0.0, -4.0, -11.0, # View-point
82
+ 0.0, 1.0, 0.0 ) # Up-vector
83
+
84
+ # Draw a textured quad
85
+ glRotatef( 0.05*x.to_f + t.to_f*5.0, 0.0, 1.0, 0.0 )
86
+ glBegin( GL_QUADS )
87
+ glTexCoord2f( -20.0, 20.0 )
88
+ glVertex3f( -50.0, 0.0, -50.0 )
89
+ glTexCoord2f( 20.0, 20.0 )
90
+ glVertex3f( 50.0, 0.0, -50.0 )
91
+ glTexCoord2f( 20.0, -20.0 )
92
+ glVertex3f( 50.0, 0.0, 50.0 )
93
+ glTexCoord2f( -20.0, -20.0 )
94
+ glVertex3f( -50.0, 0.0, 50.0 )
95
+ glEnd()
96
+
97
+ # Swap buffers
98
+ glfwSwapBuffers()
99
+
100
+ # Check if the ESC key was pressed or the window was closed
101
+ running = ( glfwGetKey( GLFW_KEY_ESC ) == GLFW_RELEASE &&
102
+ glfwGetWindowParam( GLFW_OPENED ) == true )
103
+ end
104
+
Binary file
@@ -0,0 +1,837 @@
1
+ #========================================================================
2
+ # This is a simple, but cool particle engine (buzz-word meaning many
3
+ # small objects that are treated as points and drawn as textures
4
+ # projected on simple geometry).
5
+ #
6
+ # This demonstration generates a colorful fountain-like animation. It
7
+ # uses several advanced OpenGL teqhniques:
8
+ #
9
+ # 1) Lighting (per vertex)
10
+ # 2) Alpha blending
11
+ # 3) Fog
12
+ # 4) Texturing
13
+ # 5) Display lists (for drawing the static environment geometry)
14
+ # 6) OpenGL 2.0 point sprites (for particle drawing if available)
15
+ # 7) GL_EXT_separate_specular_color is used (if available)
16
+ #
17
+ # To run a fixed length benchmark (60 s), use the command line switch -b.
18
+ #
19
+ # One more thing: Press 'w' during the demo to toggle wireframe mode.
20
+ #========================================================================
21
+ #
22
+ # Converted to ruby from GLFW example particles.c
23
+ #
24
+ # Ruby version notes:
25
+ #
26
+ # Number of particles had to be decreased 10-fold to accomodate for ruby
27
+ # speed (or lack of thereof) - interpreted languages are not exactly suited
28
+ # for realtime processing of large amounts of data, and ruby is no exception.
29
+ #
30
+ # Using point sprites and immediate mode, the ruby version is about 60x
31
+ # slower then the C version (assuming equal number of particles). If
32
+ # you need large-scale particle system, better solution would be to
33
+ # either offload as much as possible to the GPU or write it in C as
34
+ # ruby extension/module.
35
+ #
36
+ # Also I didn't use vertex arrays/buffers, because converting between ruby
37
+ # and C representation of variables each frame is actually slower then the
38
+ # function call overhead of OpenGL immediate mode.
39
+
40
+ require 'opengl'
41
+ require 'glfw'
42
+ include Gl,Glu,Glfw,Math
43
+
44
+ # Desired fullscreen resolution
45
+ WIDTH = 640
46
+ HEIGHT = 480
47
+
48
+ #========================================================================
49
+ # Type definitions
50
+ #========================================================================
51
+
52
+ class Vec
53
+ attr_accessor :x,:y,:z
54
+ end
55
+
56
+ #========================================================================
57
+ # Program control global variables
58
+ #========================================================================
59
+
60
+ # "Running" flag (true if program shall continue to run)
61
+ $running = true
62
+
63
+ # Window dimensions
64
+ $width = 0
65
+ $height = 0
66
+
67
+ # "wireframe" flag (true if we use wireframe view)
68
+ $wireframe = false
69
+
70
+ #========================================================================
71
+ # Texture declarations (we hard-code them into the source code, since
72
+ # they are so simple)
73
+ #========================================================================
74
+
75
+ P_TEX_WIDTH = 8 # Particle texture dimensions
76
+ P_TEX_HEIGHT = 8
77
+ F_TEX_WIDTH = 16 # Floor texture dimensions
78
+ F_TEX_HEIGHT = 16
79
+
80
+ # Texture object IDs
81
+ $particle_tex_id = 0
82
+ $floor_tex_id = 0
83
+
84
+ # Particle texture (a simple spot)
85
+ $particle_texture = [
86
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87
+ 0x00, 0x00, 0x11, 0x22, 0x22, 0x11, 0x00, 0x00,
88
+ 0x00, 0x11, 0x33, 0x88, 0x77, 0x33, 0x11, 0x00,
89
+ 0x00, 0x22, 0x88, 0xff, 0xee, 0x77, 0x22, 0x00,
90
+ 0x00, 0x22, 0x77, 0xee, 0xff, 0x88, 0x22, 0x00,
91
+ 0x00, 0x11, 0x33, 0x77, 0x88, 0x33, 0x11, 0x00,
92
+ 0x00, 0x00, 0x11, 0x33, 0x22, 0x11, 0x00, 0x00,
93
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
94
+ ]
95
+
96
+ # Floor texture (your basic checkered floor)
97
+ $floor_texture = [
98
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
99
+ 0xff, 0xf0, 0xcc, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
100
+ 0xf0, 0xcc, 0xee, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0x66, 0x30, 0x30, 0x30, 0x20, 0x30, 0x30,
101
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xee, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
102
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xcc, 0xf0, 0xf0, 0xf0, 0x30, 0x30, 0x55, 0x30, 0x30, 0x44, 0x30, 0x30,
103
+ 0xf0, 0xdd, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
104
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0x30,
105
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x33, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
106
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
107
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x30, 0x30, 0xf0, 0xff, 0xf0, 0xf0, 0xdd, 0xf0, 0xf0, 0xff,
108
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x55, 0x33, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0,
109
+ 0x30, 0x44, 0x66, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
110
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xaa, 0xf0, 0xf0, 0xcc, 0xf0,
111
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xdd, 0xf0,
112
+ 0x30, 0x30, 0x30, 0x77, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
113
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0
114
+ ]
115
+
116
+ #========================================================================
117
+ # These are fixed constants that control the particle engine. In a
118
+ # modular world, these values should be variables...
119
+ #========================================================================
120
+
121
+ # Maximum number of particles
122
+ MAX_PARTICLES = 300
123
+
124
+ # Life span of a particle (in seconds)
125
+ LIFE_SPAN = 8.0
126
+
127
+ # A new particle is born every [BIRTH_INTERVAL] second
128
+ BIRTH_INTERVAL = (LIFE_SPAN/MAX_PARTICLES.to_f)
129
+
130
+ # Particle size (meters)
131
+ PARTICLE_SIZE = 0.7
132
+
133
+ # Gravitational constant (m/s^2)
134
+ GRAVITY = 9.8
135
+
136
+ # Base initial velocity (m/s)
137
+ VELOCITY = 8.0
138
+
139
+ # Bounce friction (1.0 = no friction, 0.0 = maximum friction)
140
+ FRICTION = 0.75
141
+
142
+ # "Fountain" height (m)
143
+ FOUNTAIN_HEIGHT = 3.0
144
+
145
+ # Fountain radius (m)
146
+ FOUNTAIN_RADIUS = 1.6
147
+
148
+ # Minimum delta-time for particle phisics (s)
149
+ MIN_DELTA_T = (BIRTH_INTERVAL*1.0)
150
+
151
+ #========================================================================
152
+ # Particle system global variables
153
+ #========================================================================
154
+
155
+ # This structure holds all state for a single particle
156
+ class Particle
157
+ attr_accessor :x,:y,:z # Position in space
158
+ attr_accessor :vx,:vy,:vz # Velocity vector
159
+ attr_accessor :r,:g,:b # Color of particle
160
+ attr_accessor :life # Life of particle (1.0 = newborn, < 0.0 = dead)
161
+ attr_accessor :active # Tells if this particle is active
162
+ end
163
+
164
+ # Global vectors holding all particles. We use two vectors for double
165
+ # buffering.
166
+ $particles = Array.new(MAX_PARTICLES).collect {Particle.new}
167
+
168
+ # Global variable holding the age of the youngest particle
169
+ $min_age = 0
170
+
171
+ # Color of latest born particle (used for fountain lighting)
172
+ $glow_color = []
173
+
174
+ # Position of latest born particle (used for fountain lighting)
175
+ $glow_pos = []
176
+
177
+ #========================================================================
178
+ # Object material and fog configuration constants
179
+ #========================================================================
180
+
181
+ $fountain_diffuse = [0.7,1.0,1.0,1.0]
182
+ $fountain_specular = [1.0,1.0,1.0,1.0]
183
+ $fountain_shininess = 12.0
184
+ $floor_diffuse = [1.0,0.6,0.6,1.0]
185
+ $floor_specular = [0.6,0.6,0.6,1.0]
186
+ $floor_shininess = 18.0
187
+ $fog_color = [0.1, 0.1, 0.1, 1.0]
188
+
189
+ #========================================================================
190
+ # InitParticle() - Initialize a new particle
191
+ #========================================================================
192
+
193
+ def InitParticle( p, t )
194
+ # Start position of particle is at the fountain blow-out
195
+ p.x = 0.0
196
+ p.y = 0.0
197
+ p.z = FOUNTAIN_HEIGHT
198
+
199
+ # Start velocity is up (Z)...
200
+ p.vz = 0.7 + 0.3 * rand()
201
+
202
+ # ...and a randomly chosen X/Y direction
203
+ xy_angle = (2.0*PI) * rand()
204
+ p.vx = 0.4 * cos( xy_angle )
205
+ p.vy = 0.4 * sin( xy_angle )
206
+
207
+ # Scale velocity vector according to a time-varying velocity
208
+ velocity = VELOCITY*(0.8 + 0.1* (sin( 0.5*t )+sin( 1.31*t )))
209
+ p.vx *= velocity
210
+ p.vy *= velocity
211
+ p.vz *= velocity
212
+
213
+ # Color is time-varying
214
+ p.r = 0.7 + 0.3 * sin( 0.34*t + 0.1 )
215
+ p.g = 0.6 + 0.4 * sin( 0.63*t + 1.1 )
216
+ p.b = 0.6 + 0.4 * sin( 0.91*t + 2.1 )
217
+
218
+ # Store settings for fountain glow lighting
219
+ $glow_pos[0] = 0.4 * sin( 1.34*t )
220
+ $glow_pos[1] = 0.4 * sin( 3.11*t )
221
+ $glow_pos[2] = FOUNTAIN_HEIGHT + 1.0
222
+ $glow_pos[3] = 1.0
223
+ $glow_color[0] = p.r
224
+ $glow_color[1] = p.g
225
+ $glow_color[2] = p.b
226
+ $glow_color[3] = 1.0
227
+
228
+ # The particle is new-born and active
229
+ p.life = 1.0
230
+ p.active = true
231
+ end
232
+
233
+ #========================================================================
234
+ # UpdateParticle() - Update a particle
235
+ #========================================================================
236
+
237
+ FOUNTAIN_R2 = (FOUNTAIN_RADIUS+PARTICLE_SIZE/2)*(FOUNTAIN_RADIUS+PARTICLE_SIZE/2)
238
+
239
+ def UpdateParticle( p, dt )
240
+ # If the particle is not active, we need not do anything
241
+ return if( !p.active )
242
+
243
+ # The particle is getting older...
244
+ p.life = p.life - dt * (1.0 / LIFE_SPAN)
245
+
246
+ # Did the particle die?
247
+ if( p.life <= 0.0 )
248
+ p.active = false
249
+ return
250
+ end
251
+
252
+ # Update particle velocity (apply gravity)
253
+ p.vz = p.vz - GRAVITY * dt
254
+
255
+ # Update particle position
256
+ p.x = p.x + p.vx * dt;
257
+ p.y = p.y + p.vy * dt;
258
+ p.z = p.z + p.vz * dt;
259
+
260
+ # Simple collision detection + response
261
+ if( p.vz < 0.0 )
262
+ # Particles should bounce on the fountain (with friction)
263
+ if( (p.x*p.x + p.y*p.y) < FOUNTAIN_R2 &&
264
+ p.z < (FOUNTAIN_HEIGHT + PARTICLE_SIZE/2) )
265
+ p.vz = -FRICTION * p.vz
266
+ p.z = FOUNTAIN_HEIGHT + PARTICLE_SIZE/2 +
267
+ FRICTION * (FOUNTAIN_HEIGHT +
268
+ PARTICLE_SIZE/2 - p.z)
269
+
270
+ # Particles should bounce on the floor (with friction)
271
+ elsif( p.z < PARTICLE_SIZE/2 )
272
+ p.vz = -FRICTION * p.vz
273
+ p.z = PARTICLE_SIZE/2 +
274
+ FRICTION * (PARTICLE_SIZE/2 - p.z)
275
+ end
276
+ end
277
+ end
278
+
279
+ #========================================================================
280
+ # ParticleEngine() - The main frame for the particle engine. Called once
281
+ # per frame.
282
+ #========================================================================
283
+
284
+ def ParticleEngine( t, dt)
285
+ # Update particles (iterated several times per frame if dt is too
286
+ # large)
287
+ while( dt > 0.0 )
288
+ # Calculate delta time for this iteration
289
+ dt2 = dt < MIN_DELTA_T ? dt : MIN_DELTA_T
290
+
291
+ # Update particles
292
+ MAX_PARTICLES.times do |i|
293
+ UpdateParticle( $particles[ i ], dt2 )
294
+ end
295
+
296
+ # Increase minimum age
297
+ $min_age += dt2
298
+
299
+ # Should we create any new particle(s)?
300
+ while( $min_age >= BIRTH_INTERVAL )
301
+ $min_age -= BIRTH_INTERVAL
302
+
303
+ # Find a dead particle to replace with a new one
304
+ MAX_PARTICLES.times do |i|
305
+ if( !$particles[ i ].active )
306
+ InitParticle( $particles[ i ], t + $min_age )
307
+ UpdateParticle( $particles[ i ], $min_age )
308
+ break
309
+ end
310
+ end
311
+ end
312
+
313
+ # Decrease frame delta time
314
+ dt -= dt2
315
+ end
316
+ end
317
+
318
+ #========================================================================
319
+ # DrawParticles() - Draw all active particles. We use OpenGL 1.1 vertex
320
+ # arrays for this in order to accelerate the drawing.
321
+ #========================================================================
322
+
323
+ BATCH_PARTICLES = 70 # Number of particles to draw in each batch
324
+ # (70 corresponds to 7.5 KB = will not blow
325
+ # the L1 data cache on most CPUs)
326
+ PARTICLE_VERTS = 4 # Number of vertices per particle
327
+
328
+ def DrawParticles(t,dt)
329
+ # Don't update z-buffer, since all particles are transparent!
330
+ glDepthMask( GL_FALSE )
331
+
332
+ # Enable blending
333
+ glEnable( GL_BLEND )
334
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE )
335
+
336
+ # Select particle texture
337
+ if( !$wireframe )
338
+ glEnable( GL_TEXTURE_2D )
339
+ glBindTexture( GL_TEXTURE_2D, $particle_tex_id )
340
+ end
341
+
342
+ # Perform particle physics in this thread
343
+ ParticleEngine( t, dt )
344
+
345
+ if (Gl.is_available?(2.0)) # use point sprites if available
346
+ glPointParameterfv( GL_POINT_DISTANCE_ATTENUATION, [1.0,0.0,0.01] )
347
+ glPointParameterf( GL_POINT_FADE_THRESHOLD_SIZE, 60.0 )
348
+ glPointParameterf( GL_POINT_SIZE_MIN, 1.0 )
349
+ glPointParameterf( GL_POINT_SIZE_MAX, 1024.0 )
350
+
351
+ glTexEnvf( GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE )
352
+
353
+
354
+ glEnable( GL_POINT_SPRITE)
355
+
356
+ glPointSize( $height/14.0 )
357
+
358
+ glBegin( GL_POINTS );
359
+ $particles.each do |p|
360
+ next if !p.active
361
+
362
+ alpha = 4.0 * p.life
363
+ alpha = 1.0 if alpha > 1.0
364
+
365
+ glColor4f(p.r,p.g,p.b,alpha)
366
+ glVertex3f(p.x,p.y,p.z)
367
+ end
368
+ glEnd()
369
+
370
+ glDisable( GL_POINT_SPRITE )
371
+ else
372
+ quad_lower_left = Vec.new
373
+ quad_lower_right = Vec.new
374
+
375
+ mat = glGetFloatv( GL_MODELVIEW_MATRIX )
376
+ mat.flatten!
377
+ quad_lower_left.x = (-PARTICLE_SIZE/2) * (mat[0] + mat[1])
378
+ quad_lower_left.y = (-PARTICLE_SIZE/2) * (mat[4] + mat[5])
379
+ quad_lower_left.z = (-PARTICLE_SIZE/2) * (mat[8] + mat[9])
380
+ quad_lower_right.x = (PARTICLE_SIZE/2) * (mat[0] - mat[1])
381
+ quad_lower_right.y = (PARTICLE_SIZE/2) * (mat[4] - mat[5])
382
+ quad_lower_right.z = (PARTICLE_SIZE/2) * (mat[8] - mat[9])
383
+
384
+ glBegin(GL_QUADS)
385
+ $particles.each do |p|
386
+ next if !p.active
387
+ # Calculate particle intensity (we set it to max during 75%
388
+ # of its life, then it fades out)
389
+ alpha = 4.0 * p.life
390
+ alpha = 1.0 if alpha > 1.0
391
+
392
+ glColor4f(p.r,p.g,p.b,alpha)
393
+ glTexCoord2f(0.0,0.0)
394
+ glVertex3f(p.x + quad_lower_left.x,
395
+ p.y + quad_lower_left.y,
396
+ p.z + quad_lower_left.z)
397
+
398
+ glTexCoord2f(1.0,0.0)
399
+ glVertex3f(p.x + quad_lower_right.x,
400
+ p.y + quad_lower_right.y,
401
+ p.z + quad_lower_right.z)
402
+
403
+
404
+ glTexCoord2f(1.0,1.0)
405
+ glVertex3f(p.x - quad_lower_left.x,
406
+ p.y - quad_lower_left.y,
407
+ p.z - quad_lower_left.z)
408
+
409
+ glTexCoord2f(0.0,1.0)
410
+ glVertex3f(p.x - quad_lower_right.x,
411
+ p.y - quad_lower_right.y,
412
+ p.z - quad_lower_right.z)
413
+ end
414
+ glEnd()
415
+ end
416
+
417
+ # Disable texturing and blending
418
+ glDisable( GL_TEXTURE_2D )
419
+ glDisable( GL_BLEND )
420
+
421
+ # Allow Z-buffer updates again
422
+ glDepthMask( GL_TRUE )
423
+ end
424
+
425
+ #========================================================================
426
+ # Fountain geometry specification
427
+ #========================================================================
428
+
429
+ FOUNTAIN_SIDE_POINTS = 14
430
+ FOUNTAIN_SWEEP_STEPS = 32
431
+
432
+ $fountain_side = [
433
+ 1.2, 0.0, 1.0, 0.2, 0.41, 0.3, 0.4, 0.35,
434
+ 0.4, 1.95, 0.41, 2.0, 0.8, 2.2, 1.2, 2.4,
435
+ 1.5, 2.7, 1.55, 2.95, 1.6, 3.0, 1.0, 3.0,
436
+ 0.5, 3.0, 0.0, 3.0
437
+ ]
438
+
439
+ $fountain_normal = [
440
+ 1.0000, 0.0000, 0.6428, 0.7660, 0.3420, 0.9397, 1.0000, 0.0000,
441
+ 1.0000, 0.0000, 0.3420,-0.9397, 0.4226,-0.9063, 0.5000,-0.8660,
442
+ 0.7660,-0.6428, 0.9063,-0.4226, 0.0000,1.00000, 0.0000,1.00000,
443
+ 0.0000,1.00000, 0.0000,1.00000
444
+ ]
445
+
446
+ #========================================================================
447
+ # DrawFountain() - Draw a fountain
448
+ #========================================================================
449
+
450
+ def DrawFountain
451
+ @@fountain_list ||= 0 # static variable
452
+
453
+ # The first time, we build the fountain display list
454
+ if( @@fountain_list == 0)
455
+ # Start recording of a new display list
456
+ @@fountain_list = glGenLists( 1 )
457
+ glNewList( @@fountain_list, GL_COMPILE_AND_EXECUTE )
458
+
459
+ # Set fountain material
460
+ glMaterialfv( GL_FRONT, GL_DIFFUSE, $fountain_diffuse )
461
+ glMaterialfv( GL_FRONT, GL_SPECULAR, $fountain_specular )
462
+ glMaterialf( GL_FRONT, GL_SHININESS, $fountain_shininess )
463
+
464
+ # Build fountain using triangle strips
465
+ 0.upto(FOUNTAIN_SIDE_POINTS-1-1) do |n|
466
+ glBegin( GL_TRIANGLE_STRIP );
467
+ 0.upto(FOUNTAIN_SWEEP_STEPS) do |m|
468
+ angle = m * (2.0*PI/FOUNTAIN_SWEEP_STEPS.to_f)
469
+ x = cos( angle )
470
+ y = sin( angle )
471
+
472
+ # Draw triangle strip
473
+ glNormal3f( x * $fountain_normal[ n*2+2 ],
474
+ y * $fountain_normal[ n*2+2 ],
475
+ $fountain_normal[ n*2+3 ] )
476
+ glVertex3f( x * $fountain_side[ n*2+2 ],
477
+ y * $fountain_side[ n*2+2 ],
478
+ $fountain_side[ n*2+3 ] )
479
+ glNormal3f( x * $fountain_normal[ n*2 ],
480
+ y * $fountain_normal[ n*2 ],
481
+ $fountain_normal[ n*2+1 ] )
482
+ glVertex3f( x * $fountain_side[ n*2 ],
483
+ y * $fountain_side[ n*2 ],
484
+ $fountain_side[ n*2+1 ] )
485
+ end
486
+ glEnd()
487
+ end
488
+
489
+ # End recording of display list
490
+ glEndList()
491
+ else
492
+ # Playback display list
493
+ glCallList( @@fountain_list )
494
+ end
495
+ end
496
+
497
+ #========================================================================
498
+ # TesselateFloor() - Recursive function for building variable tesselated
499
+ # floor
500
+ #========================================================================
501
+
502
+ def TesselateFloor( x1,y1,x2,y2,recursion )
503
+ # Last recursion?
504
+ if( recursion >= 5 )
505
+ delta = 999999.0
506
+ else
507
+ x = x1.abs < x2.abs ? x1.abs : x2.abs
508
+ y = y1.abs < y2.abs ? y1.abs : y2.abs
509
+ delta = x*x + y*y
510
+ end
511
+
512
+ # Recurse further?
513
+ if( delta < 0.1 )
514
+ x = (x1+x2) * 0.5;
515
+ y = (y1+y2) * 0.5;
516
+ TesselateFloor( x1,y1, x, y, recursion + 1 )
517
+ TesselateFloor( x,y1, x2, y, recursion + 1 )
518
+ TesselateFloor( x1, y, x,y2, recursion + 1 )
519
+ TesselateFloor( x, y, x2,y2, recursion + 1 )
520
+ else
521
+ glTexCoord2f( x1*30.0, y1*30.0 )
522
+ glVertex3f( x1*80.0, y1*80.0 , 0.0 )
523
+ glTexCoord2f( x2*30.0, y1*30.0 )
524
+ glVertex3f( x2*80.0, y1*80.0 , 0.0 )
525
+ glTexCoord2f( x2*30.0, y2*30.0 )
526
+ glVertex3f( x2*80.0, y2*80.0 , 0.0 )
527
+ glTexCoord2f( x1*30.0, y2*30.0 )
528
+ glVertex3f( x1*80.0, y2*80.0 , 0.0 )
529
+ end
530
+ end
531
+
532
+ #========================================================================
533
+ # DrawFloor() - Draw floor. We builde the floor recursively, and let the
534
+ # tesselation in the centre (near x,y=0,0) be high, while the selleation
535
+ # around the edges be low.
536
+ #========================================================================
537
+
538
+ def DrawFloor
539
+ @@floor_list ||= 0
540
+
541
+ # Select floor texture
542
+ if( !$wireframe )
543
+ glEnable( GL_TEXTURE_2D )
544
+ glBindTexture( GL_TEXTURE_2D, $floor_tex_id )
545
+ end
546
+
547
+ # The first time, we build the floor display list
548
+ if( @@floor_list == 0)
549
+ # Start recording of a new display list
550
+ @@floor_list = glGenLists( 1 )
551
+ glNewList( @@floor_list, GL_COMPILE_AND_EXECUTE )
552
+
553
+ # Set floor material
554
+ glMaterialfv( GL_FRONT, GL_DIFFUSE, $floor_diffuse )
555
+ glMaterialfv( GL_FRONT, GL_SPECULAR, $floor_specular )
556
+ glMaterialf( GL_FRONT, GL_SHININESS, $floor_shininess )
557
+
558
+ # Draw floor as a bunch of triangle strips (high tesselation
559
+ # improves lighting)
560
+ glNormal3f( 0.0, 0.0, 1.0 )
561
+ glBegin( GL_QUADS )
562
+ TesselateFloor( -1.0,-1.0, 0.0,0.0, 0 )
563
+ TesselateFloor( 0.0,-1.0, 1.0,0.0, 0 )
564
+ TesselateFloor( 0.0, 0.0, 1.0,1.0, 0 )
565
+ TesselateFloor( -1.0, 0.0, 0.0,1.0, 0 )
566
+ glEnd()
567
+
568
+ # End recording of display list
569
+ glEndList()
570
+ else
571
+ # Playback display list
572
+ glCallList( @@floor_list )
573
+ end
574
+
575
+ glDisable( GL_TEXTURE_2D )
576
+ end
577
+
578
+ #========================================================================
579
+ # SetupLights() - Position and configure light sources
580
+ #========================================================================
581
+
582
+ def SetupLights
583
+ # Set light source 1 parameters
584
+ l1pos = [0.0,-9.0, 8.0, 1.0]
585
+ l1amb = [0.2, 0.2, 0.2, 1.0]
586
+ l1dif = [0.8, 0.4, 0.2, 1.0]
587
+ l1spec = [1.0, 0.6, 0.2, 0.0]
588
+
589
+ # Set light source 2 parameters
590
+ l2pos = [-15.0,12.0, 1.5, 1.0]
591
+ l2amb = [0.0, 0.0, 0.0, 1.0]
592
+ l2dif = [0.2, 0.4, 0.8, 1.0]
593
+ l2spec = [0.2, 0.6, 1.0, 0.0]
594
+
595
+ # Configure light sources in OpenGL
596
+ glLightfv( GL_LIGHT1, GL_POSITION, l1pos )
597
+ glLightfv( GL_LIGHT1, GL_AMBIENT, l1amb )
598
+ glLightfv( GL_LIGHT1, GL_DIFFUSE, l1dif )
599
+ glLightfv( GL_LIGHT1, GL_SPECULAR, l1spec )
600
+ glLightfv( GL_LIGHT2, GL_POSITION, l2pos )
601
+ glLightfv( GL_LIGHT2, GL_AMBIENT, l2amb )
602
+ glLightfv( GL_LIGHT2, GL_DIFFUSE, l2dif )
603
+ glLightfv( GL_LIGHT2, GL_SPECULAR, l2spec )
604
+ glLightfv( GL_LIGHT3, GL_POSITION, $glow_pos )
605
+ glLightfv( GL_LIGHT3, GL_DIFFUSE, $glow_color )
606
+ glLightfv( GL_LIGHT3, GL_SPECULAR, $glow_color )
607
+
608
+ # Enable light sources
609
+ glEnable( GL_LIGHT1 )
610
+ glEnable( GL_LIGHT2 )
611
+ glEnable( GL_LIGHT3 )
612
+ end
613
+
614
+ #========================================================================
615
+ # Draw() - Main rendering function
616
+ #========================================================================
617
+
618
+ def Draw( t )
619
+ @@t_old ||= 0.0
620
+
621
+ # Calculate frame-to-frame delta time
622
+ dt = (t-@@t_old)
623
+ @@t_old = t
624
+
625
+ # Setup viewport
626
+ glViewport( 0, 0, $width, $height )
627
+
628
+ # Clear color and Z-buffer
629
+ glClearColor( 0.1, 0.1, 0.1, 1.0 )
630
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
631
+
632
+ # Setup projection
633
+ glMatrixMode( GL_PROJECTION )
634
+ glLoadIdentity()
635
+ gluPerspective( 65.0, $width.to_f/$height.to_f, 1.0, 60.0 )
636
+
637
+ # Setup camera
638
+ glMatrixMode( GL_MODELVIEW )
639
+ glLoadIdentity()
640
+
641
+ # Rotate camera
642
+ angle_x = 90.0 - 10.0
643
+ angle_y = 10.0 * sin( 0.3 * t )
644
+ angle_z = 10.0 * t
645
+ glRotated( -angle_x, 1.0, 0.0, 0.0 )
646
+ glRotated( -angle_y, 0.0, 1.0, 0.0 )
647
+ glRotated( -angle_z, 0.0, 0.0, 1.0 )
648
+
649
+ # Translate camera
650
+ xpos = 15.0 * sin( (PI/180.0) * angle_z ) +
651
+ 2.0 * sin( (PI/180.0) * 3.1 * t )
652
+ ypos = -15.0 * cos( (PI/180.0) * angle_z ) +
653
+ 2.0 * cos( (PI/180.0) * 2.9 * t )
654
+ zpos = 4.0 + 2.0 * cos( (PI/180.0) * 4.9 * t )
655
+ glTranslated( -xpos, -ypos, -zpos )
656
+
657
+ # Enable face culling
658
+ glFrontFace( GL_CCW )
659
+ glCullFace( GL_BACK )
660
+ glEnable( GL_CULL_FACE )
661
+
662
+ # Enable lighting
663
+ SetupLights()
664
+ glEnable( GL_LIGHTING )
665
+
666
+ # Enable fog (dim details far away)
667
+ glEnable( GL_FOG )
668
+ glFogi( GL_FOG_MODE, GL_EXP )
669
+ glFogf( GL_FOG_DENSITY, 0.05 )
670
+ glFogfv( GL_FOG_COLOR, $fog_color )
671
+
672
+ # Draw floor
673
+ DrawFloor()
674
+
675
+ # Enable Z-buffering
676
+ glEnable( GL_DEPTH_TEST )
677
+ glDepthFunc( GL_LEQUAL )
678
+ glDepthMask( GL_TRUE )
679
+
680
+ # Draw fountain
681
+ DrawFountain()
682
+
683
+ # Disable fog & lighting
684
+ glDisable( GL_LIGHTING )
685
+ glDisable( GL_FOG )
686
+
687
+ # Draw all particles (must be drawn after all solid objects have been
688
+ # drawn!)
689
+ DrawParticles( t, dt )
690
+
691
+ # Z-buffer not needed anymore
692
+ glDisable( GL_DEPTH_TEST )
693
+ end
694
+
695
+ #========================================================================
696
+ # Resize() - GLFW window resize callback function
697
+ #========================================================================
698
+
699
+ Resize = lambda do |x,y|
700
+ $width = x
701
+ $height = y > 0 ? y : 1 # Prevent division by zero in aspect calc.
702
+ end
703
+
704
+ #========================================================================
705
+ # Input callback functions
706
+ #========================================================================
707
+
708
+ KeyFun = lambda do |key,action|
709
+ if( action == GLFW_PRESS )
710
+ case ( key )
711
+ when GLFW_KEY_ESC
712
+ $running = false
713
+ when ?W
714
+ $wireframe = !$wireframe
715
+ glPolygonMode( GL_FRONT_AND_BACK,
716
+ $wireframe ? GL_LINE : GL_FILL )
717
+ else
718
+ end
719
+ end
720
+ end
721
+
722
+ #========================================================================
723
+ # main()
724
+ #========================================================================
725
+
726
+ benchmark = false
727
+
728
+ # Check command line arguments
729
+ ARGV.each do |arg|
730
+ case arg
731
+ when "-b" # Use benchmarking?
732
+ benchmark = true
733
+ when /psn_/
734
+ # With a Finder launch on Mac OS X we get a bogus -psn_0_46268417
735
+ # kind of argument (actual numbers vary). Ignore it.
736
+ else
737
+ puts "Usage: #{$0} [options]"
738
+ puts ""
739
+ puts "Options:"
740
+ puts " -b Benchmark (run program for 60 s)"
741
+ puts " -s Run program as single thread (default is to use two threads)"
742
+ puts " -? Display this text"
743
+ puts ""
744
+ puts "Program runtime controls:"
745
+ puts " w Toggle wireframe mode"
746
+ puts " ESC Exit program"
747
+ exit
748
+ end
749
+ end
750
+
751
+ # Open OpenGL fullscreen window
752
+ if( glfwOpenWindow( WIDTH, HEIGHT, 5,6,5,0, 16,0, GLFW_FULLSCREEN ) == false)
753
+ exit
754
+ end
755
+
756
+ # Set window title
757
+ glfwSetWindowTitle( "Particle engine" )
758
+
759
+ # Disable VSync (we want to get as high FPS as possible!)
760
+ glfwSwapInterval( 0 )
761
+
762
+ # Window resize callback function
763
+ glfwSetWindowSizeCallback( Resize )
764
+
765
+ # Set keyboard input callback function
766
+ glfwSetKeyCallback( KeyFun )
767
+
768
+ # Upload particle texture
769
+ $particle_tex_id,* = glGenTextures( 1 )
770
+ glBindTexture( GL_TEXTURE_2D, $particle_tex_id )
771
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 )
772
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP )
773
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP )
774
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR )
775
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR )
776
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, P_TEX_WIDTH, P_TEX_HEIGHT,
777
+ 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, $particle_texture.pack("C*") )
778
+
779
+ # Upload floor texture
780
+ $floor_tex_id,* = glGenTextures( 1)
781
+ glBindTexture( GL_TEXTURE_2D, $floor_tex_id )
782
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 )
783
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT )
784
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT )
785
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR )
786
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR )
787
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, F_TEX_WIDTH, F_TEX_HEIGHT,
788
+ 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, $floor_texture.pack("C*") )
789
+
790
+ # Check if we have GL_EXT_separate_specular_color, and if so use it
791
+ # (This extension should ALWAYS be used when OpenGL lighting is used
792
+ # together with texturing, since it gives more realistic results)
793
+ if( Gl.is_available?( "GL_EXT_separate_specular_color" ) )
794
+ glLightModeli( GL_LIGHT_MODEL_COLOR_CONTROL_EXT,
795
+ GL_SEPARATE_SPECULAR_COLOR_EXT )
796
+ end
797
+
798
+ # Set filled polygon mode as default (not wireframe)
799
+ glPolygonMode( GL_FRONT_AND_BACK, GL_FILL )
800
+ $wireframe = false
801
+
802
+ # Clear particle system
803
+ MAX_PARTICLES.times do |i|
804
+ $particles[ i ].active = false
805
+ end
806
+ $min_age = 0.0
807
+
808
+ # Main loop
809
+ t0 = glfwGetTime()
810
+ frames = 0
811
+ while( $running )
812
+ # Get frame time
813
+ t = glfwGetTime() - t0
814
+
815
+ # Draw...
816
+ Draw( t )
817
+
818
+ # Swap buffers
819
+ glfwSwapBuffers()
820
+
821
+ # Check if window was closed
822
+ $running = $running && (glfwGetWindowParam( GLFW_OPENED ) == true)
823
+
824
+ # Increase frame count
825
+ frames += 1
826
+
827
+ # End of benchmark?
828
+ if( benchmark && t >= 60.0 )
829
+ $running = false
830
+ end
831
+ end
832
+ t = glfwGetTime() - t0
833
+
834
+
835
+ # Display profiling information
836
+ printf( "%d frames in %.2f seconds = %.1f FPS\n\n", frames, t, frames.to_f / t )
837
+