rage 0.1

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.
@@ -0,0 +1,91 @@
1
+ # Input handler constructs and methods
2
+ #
3
+ # Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
4
+ # Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
5
+
6
+ module RAGE
7
+
8
+ # FIXME turn into callback interface
9
+
10
+ # Handles and redirects user events to registered callbacks.
11
+ class InputHandler
12
+
13
+ # Invoked during main game execution cycle to handle any SDL input events
14
+ def self.handle(event)
15
+
16
+ @@left_button_pressed = false unless defined? @@left_button_pressed
17
+ @@right_button_pressed = false unless defined? @@right_button_pressed
18
+
19
+ case event
20
+ when SDL::Event2::Quit
21
+ exit
22
+
23
+ when SDL::Event2::KeyDown
24
+ case event.sym
25
+ when SDL::Key::Q, SDL::Key::ESCAPE
26
+ exit
27
+ when SDL::Key::W
28
+ Game.wireframe_mode= !Game.wireframe_mode
29
+ end
30
+
31
+ when SDL::Event::MouseMotion
32
+ # get state of mouse buttons
33
+ left_pressed = ((event.state & SDL::Mouse::BUTTON_LMASK) != 0)
34
+ right_pressed = ((event.state & SDL::Mouse::BUTTON_RMASK) != 0)
35
+
36
+ # if left button is down, rotate camera
37
+ if left_pressed
38
+ xpos, ypos, zpos = to_3d_coordinates(event.x, event.y)
39
+ oxpos, oypos, ozpos = to_3d_coordinates(event.x-event.xrel, event.y-event.yrel)
40
+
41
+ if xpos > oxpos
42
+ Game.current_viewport.camera.xrotate += 1
43
+ elsif xpos < oxpos
44
+ Game.current_viewport.camera.xrotate -= 1
45
+ end
46
+
47
+ if ypos > oypos
48
+ Game.current_viewport.camera.yrotate += 1
49
+ elsif ypos < oypos
50
+ Game.current_viewport.camera.yrotate -= 1
51
+ end
52
+
53
+ if zpos > ozpos
54
+ Game.current_viewport.camera.zrotate += 1
55
+ elsif zpos < ozpos
56
+ Game.current_viewport.camera.zrotate -= 1
57
+ end
58
+
59
+ # if right is down pan camera
60
+ elsif right_pressed
61
+ if event.xrel > 0
62
+ Game.current_viewport.camera.pos[0] -= 1
63
+ elsif event.xrel < 0
64
+ Game.current_viewport.camera.pos[0] += 1
65
+ end
66
+
67
+ if event.yrel > 0
68
+ Game.current_viewport.camera.pos[1] += 1
69
+ elsif event.yrel < 0
70
+ Game.current_viewport.camera.pos[1] -= 1
71
+ end
72
+
73
+ end
74
+
75
+ when SDL::Event::MouseButtonDown
76
+ # zoom out the camera
77
+ if event.button == 5 # wheeldown
78
+ Game.current_viewport.camera.pos[2] += 1
79
+ end
80
+
81
+ when SDL::Event::MouseButtonUp
82
+ # zoom in the camera
83
+ if event.button == 4 # wheel up
84
+ Game.current_viewport.camera.pos[2] -= 1
85
+ end
86
+
87
+ end
88
+ end
89
+ end
90
+
91
+ end
@@ -0,0 +1,33 @@
1
+ # RAGE resource loader
2
+ #
3
+ # Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
4
+ # Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
5
+
6
+ require 'uri' # use uri to parse sources
7
+ require 'net/http' # get http:// based resources
8
+
9
+ module RAGE
10
+
11
+ # Loads resources from uris
12
+ class Loader
13
+
14
+ # Loads and return text resource from specified source uri
15
+ def self.load(source_uri)
16
+ Logger.info "loading resource from uri #{source_uri}"
17
+ data = nil
18
+ uri = URI.parse(source_uri)
19
+ if uri.scheme == "file"
20
+ data = File.read_all uri.path
21
+ elsif uri.scheme == "http"
22
+ data = Net::HTTP.get_response(uri.host, uri.path).body
23
+ # elsif FIXME support other uri types
24
+ end
25
+
26
+ return data
27
+
28
+ rescue URI::InvalidURIError
29
+ raise Exceptions::InvalidResourceUri
30
+ end
31
+
32
+ end # class loader
33
+ end # module RXSD
@@ -0,0 +1,141 @@
1
+ # Location related constructs
2
+ #
3
+ # Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
4
+ # Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
5
+
6
+ module RAGE
7
+
8
+ # Location w/ coordinates in the 3D system.
9
+ # Various entities may be associated with Location to be drawn.
10
+ class Location
11
+ # x, y, z coordinates of the location,
12
+ attr_reader :x, :y, :z
13
+
14
+ # Mesh which to draw at location
15
+ attr_reader :mesh
16
+
17
+ # TODO lights, other entities to draw at locations
18
+
19
+ # Initialize Location with argument hash, which may include
20
+ # * :x location coordinate
21
+ # * :y location coordinate
22
+ # * :z location coordinate
23
+ # * :mesh resource to draw at location
24
+ def initialize(args = {})
25
+ @x = args.has_key?(:x) ? args[:x] : 0
26
+ @y = args.has_key?(:y) ? args[:y] : 0
27
+ @z = args.has_key?(:z) ? args[:z] : 0
28
+ @mesh = args[:mesh]
29
+ end
30
+
31
+ # Update location w/ args, which may include
32
+ # * :x location coordinate
33
+ # * :y location coordinate
34
+ # * :z location coordinate
35
+ def update(args = {})
36
+ @x = args[:x] if args.has_key?(:x)
37
+ @y = args[:y] if args.has_key?(:y)
38
+ @z = args[:z] if args.has_key?(:z)
39
+ end
40
+
41
+ # Return location boundaries. This is generated by determining maxima/minima
42
+ # local coordinates of entity associated w/ location and adding those to
43
+ # the location's coordinates. Return value is an array of six values as follows
44
+ # max_x, max_y, max_z, min_x, min_y, min_z
45
+ def boundaries
46
+ max_x = max_y = max_z = min_x = min_y = min_z = 0
47
+ unless mesh.nil?
48
+ max_x, max_y, max_z, min_x, min_y, min_z = mesh.boundaries
49
+ end
50
+ return x + max_x, y + max_y, z + max_z, x + min_x, y + min_y, z + min_z
51
+ end
52
+
53
+
54
+ # Invoked during draw cycle to draw location & entity associated w/ it
55
+ def draw
56
+ Gl.glPushMatrix();
57
+
58
+ # translate coordinate system to location's coordinates
59
+ Gl.glTranslatef(x, y, z)
60
+
61
+ # draw mesh
62
+ mesh.draw
63
+
64
+ Gl.glPopMatrix();
65
+ end
66
+ end
67
+
68
+ # Singleton class managing all locations
69
+ class LocationsManager
70
+ include Singleton
71
+
72
+ # Array of locations being managed
73
+ attr_accessor :locations
74
+
75
+ def initialize
76
+ @locations = []
77
+ end
78
+
79
+ # Add location to be managed
80
+ def add(location)
81
+ @locations.push location unless @locations.include? location
82
+ end
83
+
84
+ # Empty the array of managed locations
85
+ def clear
86
+ @locations.clear
87
+ end
88
+
89
+ # Return the maxima and minima of the x,y,z coordinate values for all the
90
+ # locations being managed. Return value is an array of six values as follows
91
+ # max_x, max_y, max_z, min_x, min_y, min_z
92
+ # This method essentially gives you the "box" in which all locations being managed are in
93
+ def boundaries
94
+ max_x = max_y = max_z = min_x = min_y = min_z = 0
95
+ @locations.each { |loc|
96
+ locb = loc.boundaries
97
+ max_x = locb[0] if locb[0] > max_x
98
+ max_y = locb[1] if locb[1] > max_y
99
+ max_z = locb[2] if locb[2] > max_z
100
+ min_x = locb[3] if locb[3] < min_x
101
+ min_y = locb[4] if locb[4] < min_y
102
+ min_z = locb[5] if locb[5] < min_z
103
+ }
104
+ return max_x, max_y, max_z, min_x, min_y, min_z
105
+ end
106
+
107
+ # Return the center coordinate of location system.
108
+ # Must specify the metric which to generate center, which may be either
109
+ # * :avg - compute and return bounaries averages
110
+ # * :mean - compute and return mean of all coords
111
+ def center(metric = :mean)
112
+ if metric == :mean
113
+ ls = @locations.size
114
+ mx = my = mz = 0
115
+ @locations.each { |lm|
116
+ mx += lm.x / ls
117
+ my += lm.y / ls
118
+ mz += lm.z / ls
119
+ }
120
+ return mx,my,mz
121
+
122
+ elsif metric == :avg
123
+ b = self.boundaries
124
+ return (b[0] + b[3]) / 2, (b[1] + b[4]) / 2, (b[2] + b[5]) / 2
125
+
126
+ end
127
+ end
128
+
129
+ end
130
+
131
+ # Helper method to get 3d coords cooresponding to 2d ones via OPENGL unprojection
132
+ def to_3d_coordinates(x2, y2)
133
+ model_view = Gl.glGetDoublev Gl::GL_MODELVIEW_MATRIX
134
+ projection = Gl.glGetDoublev Gl::GL_PROJECTION_MATRIX
135
+ viewport = Gl.glGetIntegerv Gl::GL_VIEWPORT
136
+ depth = Gl.glReadPixels x2, y2, 1, 1, Gl::GL_DEPTH_COMPONENT, Gl::GL_FLOAT
137
+ x3, y3, z3 = Glu.gluUnProject x2, y2, depth[0], model_view, projection, viewport
138
+ return [x3, y3, z3]
139
+ end
140
+
141
+ end
@@ -0,0 +1,147 @@
1
+ # Mesh Resource
2
+ #
3
+ # Currently manages X3D meshes
4
+ #
5
+ # Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
6
+ # Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
7
+
8
+ # use rxsd to load x3d xsd schema, declare xsd classes, instantiate scenes
9
+ require 'rxsd'
10
+
11
+ module RAGE
12
+
13
+ # 3D mesh to be displayed on the screen.
14
+ # Contains geometry and visual properties.
15
+ # Currently implements certain parts of the X3D graphics schema.
16
+ # http://en.wikipedia.org/wiki/X3D
17
+ class Mesh
18
+ # Optional transformation params, set these to
19
+ # transformations to be factored in if needed
20
+ attr_accessor :op_translation, :op_scale, :op_rotation
21
+
22
+ # X3D schema for shared access
23
+ class_attr :x3d_schema
24
+
25
+ # X3D schema classes for shared access
26
+ class_attr :x3d_schema_classes
27
+
28
+
29
+ # Create new mesh from raw X3D mesh
30
+ def initialize(data)
31
+ # set default attributes
32
+ @op_translation = [0,0,0]
33
+ @op_scale = [1,1,1]
34
+
35
+ # load the x3d xsd schema and classes if not already done so
36
+ unless defined? @@x3d_schema
37
+ @@x3d_schema = RXSD::Parser.parse_xsd :uri => 'http://www.web3d.org/specifications/x3d-3.0.xsd' # TODO allow location which this is pulled from to be configured
38
+ @@x3d_schema_classes = @@x3d_schema.to :ruby_classes
39
+ end
40
+
41
+ # load the scene from the x3d schema instance
42
+ objs = RXSD::Parser.parse_xml(:raw => data).to(:ruby_objects, :schema => @@x3d_schema)
43
+ @scene = objs[0].scene
44
+
45
+ # FIXME get all transformations (and groups of) under scene
46
+ @tf = @scene.collision.transform
47
+ @translation = @tf.translation.to_a :type => XSDFloat
48
+ @scale = @tf.scale.to_a :type => XSDFloat
49
+ #diffuse = tf.shape.appearance.material.diffuse_color.split.collect { |c| c.to_f }
50
+ #specular = tf.shape.appearance.material.specular_color.split.collect { |c| c.to_f }
51
+ #emissive = tf.shape.appearance.material.emissive_color.split.collect { |c| c.to_f }
52
+ @coord_index = @tf.shape.indexed_face_set.coord_index.
53
+ to_a(:type => String, :delim => ",").
54
+ collect { |coords| a = coords.to_a(:type => XSDInteger); a[0...a.size-1]}.flatten # cut off the last -1
55
+ @coord_point = @tf.shape.indexed_face_set.coordinate.point.
56
+ to_a(:type => String, :delim => ",").
57
+ collect { |coords| coords.to_a :type => XSDFloat }.flatten
58
+ end
59
+
60
+ # Create location w/ specified args, associated mesh w/ it and add it to the LocationsManager
61
+ def show_at(args = {})
62
+ # XXX not a huge fan of storing location interally,
63
+ # but this is best way to do this for now
64
+ if ! defined? @location
65
+ args[:mesh] = self
66
+ @location = Location.new(args)
67
+ LocationsManager.instance.add @location
68
+ else
69
+ @location.update args
70
+ end
71
+ return @location
72
+ end
73
+
74
+
75
+ # Return center point of mesh from mesh translation provided in mesh
76
+ # and op_translation
77
+ def center
78
+ return @op_translation[0] + @translation[0],
79
+ @op_translation[1] + @translation[1],
80
+ @op_translation[2] + @translation[2]
81
+ end
82
+
83
+ # Return factor which mesh should scale to
84
+ def scale
85
+ return @scale[0] * @op_scale[0],
86
+ @scale[1] * @op_scale[1],
87
+ @scale[2] * @op_scale[2]
88
+ end
89
+
90
+ # Return mesh boundaries. This is generated by determining the maxima/minima
91
+ # coordinate points. Return value is an array of six values as follows
92
+ # max_x, max_y, max_z, min_x, min_y, min_z
93
+ def boundaries
94
+ centerx, centery, centerz = *center
95
+ max_x = max_y = max_z = min_x = min_y = min_z = 0
96
+ @coord_point.each_index { |cpi|
97
+ if cpi % 3 == 0
98
+ adjx = centerx + @coord_point[cpi]
99
+ if adjx > max_x
100
+ max_x = adjx
101
+ elsif adjx < min_x
102
+ min_x = adjx
103
+ end
104
+ elsif cpi % 3 == 1
105
+ adjy = centery + @coord_point[cpi]
106
+ if adjy > max_y
107
+ max_y = adjy
108
+ elsif adjy < min_y
109
+ min_y = adjy
110
+ end
111
+ else
112
+ adjz = centerz + @coord_point[cpi]
113
+ if adjz > max_z
114
+ max_z = adjz
115
+ elsif adjz < min_z
116
+ min_z = adjz
117
+ end
118
+ end
119
+ }
120
+ return max_x, max_y, max_z, min_x, min_y, min_z
121
+ end
122
+
123
+
124
+ # Invoked during draw cycle to draw mesh
125
+ def draw
126
+ # FIXME mesh material
127
+ #Gl.glMaterial(Gl::GL_FRONT, Gl::GL_DIFFUSE, diffuse)
128
+ #Gl.glMaterial(Gl::GL_FRONT, Gl::GL_SPECULAR, specular)
129
+ #Gl.glMaterial(Gl::GL_FRONT, Gl::GL_EMISSIVE, emissive)
130
+
131
+ # translate coordinate system to center position of mesh
132
+ Gl.glTranslatef(*center)
133
+
134
+ # scale as specified
135
+ Gl.glScalef(*scale)
136
+
137
+ # FIXME rotate according to mesh and optional params
138
+
139
+ # draw mesh
140
+ Gl.glEnableClientState(Gl::GL_VERTEX_ARRAY);
141
+ Gl.glVertexPointer(3, Gl::GL_FLOAT, 0, @coord_point);
142
+ Gl.glDrawElements(Gl::GL_QUADS, @coord_index.size, Gl::GL_UNSIGNED_INT, @coord_index);
143
+ Gl.glDisableClientState(Gl::GL_VERTEX_ARRAY);
144
+ end
145
+ end
146
+
147
+ end
@@ -0,0 +1,49 @@
1
+ # Resources constructs and methods
2
+ #
3
+ # Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
4
+ # Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
5
+
6
+ require 'singleton'
7
+
8
+ module RAGE
9
+
10
+ # Singleton class managing all RAGE resources.
11
+ # Resources should be loaded here instead as opposed to creating them manually
12
+ # so as to mantain a central management repository during game execution.
13
+ class ResourcesManager
14
+ include Singleton
15
+
16
+ # Hash of ids -> resources we are managing
17
+ attr_accessor :resources
18
+
19
+ def initialize
20
+ @resources = {}
21
+ end
22
+
23
+ # Load resource from specified args and add to manager. Args may include
24
+ # * :type type of resource to load
25
+ # * :id unique identifier to give resource
26
+ # * :uri uri of resource if appropriate
27
+ # * :color resource color if appropriate
28
+ def load_resource(args = {})
29
+ type = args[:type]
30
+ id = args[:id]
31
+
32
+ resource = nil
33
+
34
+ if type == :mesh
35
+ uri = args[:uri]
36
+ data = Loader.load uri
37
+ resource = Mesh.new(data)
38
+ elsif type == :color
39
+ color = args[:color]
40
+ resource = Color.new(:rgb => color)
41
+ # elsif other resource types
42
+ end
43
+
44
+ @resources[id] = resource
45
+ return resource
46
+ end
47
+ end
48
+
49
+ end