ruby-glfw 0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+