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.
- data/README +1 -0
- data/README.API +73 -0
- data/Rakefile +120 -0
- data/examples/boing.rb +519 -0
- data/examples/gears.rb +327 -0
- data/examples/keytest.rb +117 -0
- data/examples/listmodes.rb +20 -0
- data/examples/mipmaps.rb +104 -0
- data/examples/mipmaps.tga +0 -0
- data/examples/particles.rb +837 -0
- data/examples/pong3d.rb +741 -0
- data/examples/pong3d_field.tga +0 -0
- data/examples/pong3d_instr.tga +0 -0
- data/examples/pong3d_menu.tga +0 -0
- data/examples/pong3d_title.tga +0 -0
- data/examples/pong3d_winner1.tga +0 -0
- data/examples/pong3d_winner2.tga +0 -0
- data/examples/splitview.rb +432 -0
- data/examples/triangle.rb +89 -0
- data/examples/wave.rb +294 -0
- data/ext/glfw/glfw.c +1094 -0
- data/ext/glfw/mkrf_conf.rb +70 -0
- data/glfw-src/Makefile +220 -0
- data/glfw-src/compile.ami +61 -0
- data/glfw-src/compile.bat +217 -0
- data/glfw-src/compile.sh +607 -0
- data/glfw-src/docs/Makefile +57 -0
- data/glfw-src/docs/Reference.pdf +0 -0
- data/glfw-src/docs/UsersGuide.pdf +0 -0
- data/glfw-src/docs/cleanup.bat +22 -0
- data/glfw-src/docs/glfwdoc.sty +80 -0
- data/glfw-src/docs/glfwrm.tex +3034 -0
- data/glfw-src/docs/glfwug.tex +2024 -0
- data/glfw-src/docs/readme.txt +80 -0
- data/glfw-src/examples/Makefile.amigaos.gcc +70 -0
- data/glfw-src/examples/Makefile.amigaos.vbcc +70 -0
- data/glfw-src/examples/Makefile.dos.djgpp +71 -0
- data/glfw-src/examples/Makefile.macosx.gcc +96 -0
- data/glfw-src/examples/Makefile.win32.bcc +75 -0
- data/glfw-src/examples/Makefile.win32.cross-mgw +79 -0
- data/glfw-src/examples/Makefile.win32.cygwin +79 -0
- data/glfw-src/examples/Makefile.win32.lcc +74 -0
- data/glfw-src/examples/Makefile.win32.mgw +75 -0
- data/glfw-src/examples/Makefile.win32.msvc +74 -0
- data/glfw-src/examples/Makefile.win32.ow +74 -0
- data/glfw-src/examples/Makefile.win32.pellesc +74 -0
- data/glfw-src/examples/Makefile.x11.in +54 -0
- data/glfw-src/examples/boing.c +606 -0
- data/glfw-src/examples/bundle.sh +46 -0
- data/glfw-src/examples/gears.c +382 -0
- data/glfw-src/examples/keytest.c +264 -0
- data/glfw-src/examples/listmodes.c +48 -0
- data/glfw-src/examples/mipmaps.c +126 -0
- data/glfw-src/examples/mipmaps.tga +0 -0
- data/glfw-src/examples/mtbench.c +301 -0
- data/glfw-src/examples/mthello.c +48 -0
- data/glfw-src/examples/particles.c +1148 -0
- data/glfw-src/examples/pong3d.c +839 -0
- data/glfw-src/examples/pong3d_field.tga +0 -0
- data/glfw-src/examples/pong3d_instr.tga +0 -0
- data/glfw-src/examples/pong3d_menu.tga +0 -0
- data/glfw-src/examples/pong3d_title.tga +0 -0
- data/glfw-src/examples/pong3d_winner1.tga +0 -0
- data/glfw-src/examples/pong3d_winner2.tga +0 -0
- data/glfw-src/examples/splitview.c +506 -0
- data/glfw-src/examples/triangle.c +108 -0
- data/glfw-src/examples/wave.c +397 -0
- data/glfw-src/images/opengl.gif +0 -0
- data/glfw-src/images/osicert.gif +0 -0
- data/glfw-src/include/GL/glfw.h +486 -0
- data/glfw-src/lib/amigaos/Makefile.amigaos.gcc +128 -0
- data/glfw-src/lib/amigaos/Makefile.amigaos.vbcc +128 -0
- data/glfw-src/lib/amigaos/SDI_compiler.h +94 -0
- data/glfw-src/lib/amigaos/amigaos_enable.c +51 -0
- data/glfw-src/lib/amigaos/amigaos_fullscreen.c +319 -0
- data/glfw-src/lib/amigaos/amigaos_glext.c +61 -0
- data/glfw-src/lib/amigaos/amigaos_init.c +284 -0
- data/glfw-src/lib/amigaos/amigaos_joystick.c +359 -0
- data/glfw-src/lib/amigaos/amigaos_thread.c +494 -0
- data/glfw-src/lib/amigaos/amigaos_time.c +206 -0
- data/glfw-src/lib/amigaos/amigaos_window.c +830 -0
- data/glfw-src/lib/amigaos/platform.h +337 -0
- data/glfw-src/lib/dos/Makefile.dos.djgpp +146 -0
- data/glfw-src/lib/dos/dos_enable.c +51 -0
- data/glfw-src/lib/dos/dos_events.c +173 -0
- data/glfw-src/lib/dos/dos_fullscreen.c +101 -0
- data/glfw-src/lib/dos/dos_glext.c +59 -0
- data/glfw-src/lib/dos/dos_init.c +105 -0
- data/glfw-src/lib/dos/dos_irq.s +246 -0
- data/glfw-src/lib/dos/dos_joystick.c +94 -0
- data/glfw-src/lib/dos/dos_keyboard.c +694 -0
- data/glfw-src/lib/dos/dos_mouse.c +337 -0
- data/glfw-src/lib/dos/dos_thread.c +267 -0
- data/glfw-src/lib/dos/dos_time.c +309 -0
- data/glfw-src/lib/dos/dos_window.c +563 -0
- data/glfw-src/lib/dos/platform.h +341 -0
- data/glfw-src/lib/enable.c +295 -0
- data/glfw-src/lib/fullscreen.c +95 -0
- data/glfw-src/lib/glext.c +201 -0
- data/glfw-src/lib/image.c +629 -0
- data/glfw-src/lib/init.c +108 -0
- data/glfw-src/lib/input.c +280 -0
- data/glfw-src/lib/internal.h +210 -0
- data/glfw-src/lib/joystick.c +101 -0
- data/glfw-src/lib/macosx/Makefile.macosx.gcc +172 -0
- data/glfw-src/lib/macosx/Makefile.macosx.gcc.universal +166 -0
- data/glfw-src/lib/macosx/libglfw.pc.in +11 -0
- data/glfw-src/lib/macosx/macosx_enable.c +42 -0
- data/glfw-src/lib/macosx/macosx_fullscreen.c +126 -0
- data/glfw-src/lib/macosx/macosx_glext.c +52 -0
- data/glfw-src/lib/macosx/macosx_init.c +194 -0
- data/glfw-src/lib/macosx/macosx_joystick.c +50 -0
- data/glfw-src/lib/macosx/macosx_thread.c +414 -0
- data/glfw-src/lib/macosx/macosx_time.c +112 -0
- data/glfw-src/lib/macosx/macosx_window.c +1279 -0
- data/glfw-src/lib/macosx/platform.h +349 -0
- data/glfw-src/lib/stream.c +194 -0
- data/glfw-src/lib/tga.c +405 -0
- data/glfw-src/lib/thread.c +340 -0
- data/glfw-src/lib/time.c +83 -0
- data/glfw-src/lib/win32/Makefile.win32.bcc +265 -0
- data/glfw-src/lib/win32/Makefile.win32.cross-mgw +274 -0
- data/glfw-src/lib/win32/Makefile.win32.cygwin +279 -0
- data/glfw-src/lib/win32/Makefile.win32.lcc +246 -0
- data/glfw-src/lib/win32/Makefile.win32.mgw +243 -0
- data/glfw-src/lib/win32/Makefile.win32.msvc +242 -0
- data/glfw-src/lib/win32/Makefile.win32.ow +242 -0
- data/glfw-src/lib/win32/Makefile.win32.pellesc +242 -0
- data/glfw-src/lib/win32/glfwdll.def +67 -0
- data/glfw-src/lib/win32/glfwdll_mgw1.def +67 -0
- data/glfw-src/lib/win32/glfwdll_mgw2.def +67 -0
- data/glfw-src/lib/win32/glfwdll_pellesc.def +65 -0
- data/glfw-src/lib/win32/libglfw.pc.in +11 -0
- data/glfw-src/lib/win32/platform.h +474 -0
- data/glfw-src/lib/win32/win32_dllmain.c +60 -0
- data/glfw-src/lib/win32/win32_enable.c +155 -0
- data/glfw-src/lib/win32/win32_fullscreen.c +317 -0
- data/glfw-src/lib/win32/win32_glext.c +85 -0
- data/glfw-src/lib/win32/win32_init.c +356 -0
- data/glfw-src/lib/win32/win32_joystick.c +234 -0
- data/glfw-src/lib/win32/win32_thread.c +511 -0
- data/glfw-src/lib/win32/win32_time.c +146 -0
- data/glfw-src/lib/win32/win32_window.c +1714 -0
- data/glfw-src/lib/window.c +727 -0
- data/glfw-src/lib/x11/Makefile.x11.in +243 -0
- data/glfw-src/lib/x11/platform.h +415 -0
- data/glfw-src/lib/x11/x11_enable.c +51 -0
- data/glfw-src/lib/x11/x11_fullscreen.c +524 -0
- data/glfw-src/lib/x11/x11_glext.c +69 -0
- data/glfw-src/lib/x11/x11_init.c +275 -0
- data/glfw-src/lib/x11/x11_joystick.c +371 -0
- data/glfw-src/lib/x11/x11_keysym2unicode.c +902 -0
- data/glfw-src/lib/x11/x11_thread.c +507 -0
- data/glfw-src/lib/x11/x11_time.c +154 -0
- data/glfw-src/lib/x11/x11_window.c +1746 -0
- data/glfw-src/license.txt +21 -0
- data/glfw-src/readme.html +927 -0
- data/glfw-src/support/d/examples/Makefile +59 -0
- data/glfw-src/support/d/examples/boing.d +610 -0
- data/glfw-src/support/d/examples/gears.d +379 -0
- data/glfw-src/support/d/examples/keytest.d +272 -0
- data/glfw-src/support/d/examples/listmodes.d +48 -0
- data/glfw-src/support/d/examples/mipmaps.d +126 -0
- data/glfw-src/support/d/examples/mtbench.d +304 -0
- data/glfw-src/support/d/examples/mthello.d +54 -0
- data/glfw-src/support/d/examples/particles.d +1150 -0
- data/glfw-src/support/d/examples/pong3d.d +840 -0
- data/glfw-src/support/d/examples/splitview.d +486 -0
- data/glfw-src/support/d/examples/triangle.d +108 -0
- data/glfw-src/support/d/examples/wave.d +400 -0
- data/glfw-src/support/d/imports/gl.d +4539 -0
- data/glfw-src/support/d/imports/glfw.d +349 -0
- data/glfw-src/support/d/imports/glu.d +328 -0
- data/glfw-src/support/d/lib/glfwdll.def +64 -0
- data/glfw-src/support/d/lib/glu32.def +56 -0
- data/glfw-src/support/d/lib/makefile +12 -0
- data/glfw-src/support/d/lib/opengl32.def +372 -0
- data/glfw-src/support/d/readme.html +83 -0
- data/glfw-src/support/delphi/examples/Triangle.dpr +105 -0
- data/glfw-src/support/delphi/lib/glfw.pas +437 -0
- data/glfw-src/support/delphi/readme.html +97 -0
- data/glfw-src/support/lua/examples/gears.lua +383 -0
- data/glfw-src/support/lua/examples/test1.lua +68 -0
- data/glfw-src/support/lua/readme.html +128 -0
- data/glfw-src/support/lua/src/luaglfw.c +1179 -0
- data/glfw-src/support/lua/src/luaglfw.h +48 -0
- data/glfw-src/support/lua/src/runlua.c +82 -0
- data/glfw-src/support/masm/examples/fpc.mac +47 -0
- data/glfw-src/support/masm/examples/makeit.bat +66 -0
- data/glfw-src/support/masm/examples/triangle.asm +232 -0
- data/glfw-src/support/masm/include/glfw.inc +326 -0
- data/glfw-src/support/masm/include/glu32.inc +55 -0
- data/glfw-src/support/masm/include/opengl32.inc +372 -0
- data/glfw-src/support/masm/lib/glfwdll.lib +0 -0
- data/glfw-src/support/masm/readme.html +170 -0
- data/glfw-src/support/msvc80/GLFW.sln +26 -0
- data/glfw-src/support/msvc80/GLFW.vcproj +257 -0
- data/glfw-src/support/msvc80/GLFWDLL.vcproj +287 -0
- data/glfw-src/support/visualbasic/bindings/glfw.bas +320 -0
- data/glfw-src/support/visualbasic/bindings/glu32.bas +284 -0
- data/glfw-src/support/visualbasic/bindings/opengl32.bas +999 -0
- data/glfw-src/support/visualbasic/examples/Triangle.bas +101 -0
- data/glfw-src/support/visualbasic/readme.html +164 -0
- data/website/index.html +84 -0
- data/website/style.css +110 -0
- metadata +301 -0
data/examples/mipmaps.rb
ADDED
|
@@ -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
|
+
|