rubygl 0.1.0

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,73 @@
1
+ #include "GLContext.h"
2
+
3
+ const SDL_GLattr RED_SIZE = SDL_GL_RED_SIZE,
4
+ GREEN_SIZE = SDL_GL_GREEN_SIZE,
5
+ BLUE_SIZE = SDL_GL_BLUE_SIZE,
6
+ ALPHA_SIZE = SDL_GL_ALPHA_SIZE,
7
+ BUFFER_SIZE = SDL_GL_BUFFER_SIZE,
8
+ DOUBLEBUFFER = SDL_GL_DOUBLEBUFFER,
9
+ DEPTH_SIZE = SDL_GL_DEPTH_SIZE,
10
+ STENCIL_SIZE = SDL_GL_STENCIL_SIZE,
11
+ ACCUM_RED_SIZE = SDL_GL_ACCUM_RED_SIZE,
12
+ ACCUM_GREEN_SIZE = SDL_GL_ACCUM_GREEN_SIZE,
13
+ ACCUM_BLUE_SIZE = SDL_GL_ACCUM_BLUE_SIZE,
14
+ ACCUM_ALPHA_SIZE = SDL_GL_ACCUM_ALPHA_SIZE,
15
+ STEREO = SDL_GL_STEREO,
16
+ MULTISAMPLEBUFFERS = SDL_GL_MULTISAMPLEBUFFERS,
17
+ MULTISAMPLESAMPLES = SDL_GL_MULTISAMPLESAMPLES,
18
+ ACCELERATED_VISUAL = SDL_GL_ACCELERATED_VISUAL,
19
+ CONTEXT_MAJOR_VERSION = SDL_GL_CONTEXT_MAJOR_VERSION,
20
+ CONTEXT_MINOR_VERSION = SDL_GL_CONTEXT_MINOR_VERSION,
21
+ CONTEXT_FLAGS = SDL_GL_CONTEXT_FLAGS,
22
+ CONTEXT_PROFILE_MASK = SDL_GL_CONTEXT_PROFILE_MASK,
23
+ SHARE_WITH_CURRENT_CONTEXT = SDL_GL_SHARE_WITH_CURRENT_CONTEXT,
24
+ FRAMEBUFFER_SRGB_CAPABLE = SDL_GL_FRAMEBUFFER_SRGB_CAPABLE;
25
+
26
+ const SDL_GLcontextFlag CONTEXT_DEBUG_FLAG = SDL_GL_CONTEXT_DEBUG_FLAG,
27
+ CONTEXT_FORWARD_COMPATIBLE_FLAG = SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG,
28
+ CONTEXT_ROBUST_ACCESS_FLAG = SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG,
29
+ CONTEXT_RESET_ISOLATION_FLAG = SDL_GL_CONTEXT_RESET_ISOLATION_FLAG;
30
+
31
+ const SDL_GLprofile CONTEXT_PROFILE_CORE = SDL_GL_CONTEXT_PROFILE_CORE,
32
+ CONTEXT_PROFILE_COMPATIBILITY = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY,
33
+ CONTEXT_PROFILE_ES = SDL_GL_CONTEXT_PROFILE_ES;
34
+
35
+ int loadLibrary(const char* path)
36
+ {
37
+ return SDL_GL_LoadLibrary(path);
38
+ }
39
+
40
+ void unloadLibrary(void)
41
+ {
42
+ SDL_GL_UnloadLibrary();
43
+ }
44
+
45
+ SDL_GLContext createContext(SDL_Window* window)
46
+ {
47
+ return SDL_GL_CreateContext(window);
48
+ }
49
+
50
+ void deleteContext(SDL_GLContext context)
51
+ {
52
+ SDL_GL_DeleteContext(context);
53
+ }
54
+
55
+ int setAttribute(SDL_GLattr attr, int value)
56
+ {
57
+ return SDL_GL_SetAttribute(attr, value);
58
+ }
59
+
60
+ int makeCurrent(SDL_Window* window, SDL_GLContext context)
61
+ {
62
+ return SDL_GL_MakeCurrent(window, context);
63
+ }
64
+
65
+ int setSwapInterval(int interval)
66
+ {
67
+ return SDL_GL_SetSwapInterval(interval);
68
+ }
69
+
70
+ void swapWindow(SDL_Window* window)
71
+ {
72
+ SDL_GL_SwapWindow(window);
73
+ }
@@ -0,0 +1,26 @@
1
+ #include "Input.h"
2
+
3
+ int initInput()
4
+ {
5
+ return SDL_InitSubSystem(SDL_INIT_EVENTS);
6
+ }
7
+
8
+ void quitInput()
9
+ {
10
+ SDL_QuitSubSystem(SDL_INIT_EVENTS);
11
+ }
12
+
13
+ void addEventWatch(SDL_EventFilter filter, void* userdata)
14
+ {
15
+ SDL_AddEventWatch(filter, userdata);
16
+ }
17
+
18
+ void deleteEventWatch(SDL_EventFilter filter, void* userdata)
19
+ {
20
+ SDL_DelEventWatch(filter, userdata);
21
+ }
22
+
23
+ void pumpEvents(void)
24
+ {
25
+ SDL_PumpEvents();
26
+ }
@@ -0,0 +1,58 @@
1
+ #include "Window.h"
2
+
3
+ const SDL_WindowFlags FULLSCREEN = SDL_WINDOW_FULLSCREEN,
4
+ OPENGL = SDL_WINDOW_OPENGL,
5
+ SHOWN = SDL_WINDOW_SHOWN,
6
+ HIDDEN = SDL_WINDOW_HIDDEN,
7
+ BORDERLESS = SDL_WINDOW_BORDERLESS,
8
+ RESIZABLE = SDL_WINDOW_RESIZABLE,
9
+ MINIMIZED = SDL_WINDOW_MINIMIZED,
10
+ MAXIMIZED = SDL_WINDOW_MAXIMIZED,
11
+ INPUT_GRABBED = SDL_WINDOW_INPUT_GRABBED,
12
+ INPUT_FOCUS = SDL_WINDOW_INPUT_FOCUS,
13
+ MOUSE_FOCUS = SDL_WINDOW_MOUSE_FOCUS,
14
+ FULLSCREEN_DESKTOP = SDL_WINDOW_FULLSCREEN_DESKTOP,
15
+ FOREIGN = SDL_WINDOW_FOREIGN,
16
+ ALLOW_HIGHDPI = SDL_WINDOW_ALLOW_HIGHDPI;
17
+
18
+ int initWindow()
19
+ {
20
+ return SDL_InitSubSystem(SDL_INIT_VIDEO);
21
+ }
22
+
23
+ void quitWindow()
24
+ {
25
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
26
+ }
27
+
28
+ SDL_Window* createWindow(const char* title, int x, int y, int w, int h,
29
+ Uint32 flags)
30
+ {
31
+ return SDL_CreateWindow(title, x, y, w, h, flags);
32
+ }
33
+
34
+ void destroyWindow(SDL_Window* window)
35
+ {
36
+ SDL_DestroyWindow(window);
37
+ }
38
+
39
+ void hideWindow(SDL_Window* window)
40
+ {
41
+ SDL_HideWindow(window);
42
+ }
43
+
44
+ void showWindow(SDL_Window* window)
45
+ {
46
+ SDL_ShowWindow(window);
47
+ }
48
+
49
+ int setWindowBrightness(SDL_Window* window, float brightness)
50
+ {
51
+ return SDL_SetWindowBrightness(window, brightness);
52
+ }
53
+
54
+ int showSimpleMessageBox(Uint32 flags, const char* title, const char* message,
55
+ SDL_Window* window)
56
+ {
57
+ return SDL_ShowSimpleMessageBox(flags, title, message, window);
58
+ }
@@ -0,0 +1,25 @@
1
+ require 'ffi'
2
+
3
+ module RubyGL::Native
4
+ attach_function :initWindow, [], :int
5
+ attach_function :quitWindow, [], :void
6
+ attach_function :createWindow, [:string, :int, :int, :int, :int, :uint32], :pointer
7
+ attach_function :destroyWindow, [:pointer], :void
8
+ attach_function :hideWindow, [:pointer], :void
9
+ attach_function :showWindow, [:pointer], :void
10
+ attach_function :setWindowBrightness, [:pointer, :float], :int
11
+ attach_function :showSimpleMessageBox, [:uint32, :string, :string, :pointer], :int
12
+
13
+ attach_variable :FULLSCREEN, :int
14
+ attach_variable :OPENGL, :int
15
+ attach_variable :SHOWN, :int
16
+ attach_variable :HIDDEN, :int
17
+ attach_variable :BORDERLESS, :int
18
+ attach_variable :RESIZABLE, :int
19
+ attach_variable :MINIMIZED, :int
20
+ attach_variable :MAXIMIZED, :int
21
+ attach_variable :INPUT_FOCUS, :int
22
+ attach_variable :MOUSE_FOCUS, :int
23
+ attach_variable :FULLSCREEN_DESKTOP, :int
24
+ attach_variable :ALLOW_HIGHDPI, :int
25
+ end
@@ -0,0 +1,10 @@
1
+
2
+ module RubyGL
3
+
4
+ class InputCallback
5
+ def self.register()
6
+
7
+ end
8
+ end
9
+
10
+ end
@@ -0,0 +1,212 @@
1
+ require_relative './math'
2
+ require_relative './util'
3
+
4
+ module RubyGL
5
+
6
+ # All Point Operations Return New Points
7
+ class Point
8
+ attr_accessor :x, :y, :z
9
+
10
+ def initialize(x, y, z = 0)
11
+ @x = x
12
+ @y = y
13
+ @z = z
14
+ end
15
+
16
+ def +(point)
17
+ Point.new(@x + point.x, @y + point.y, @z + point.z)
18
+ end
19
+
20
+ def -(point)
21
+ Point.new(@x - point.x, @y - point.y, @z - point.z)
22
+ end
23
+
24
+ def scale(value)
25
+ Point.new(@x * value, @y * value, @z * value)
26
+ end
27
+
28
+ def distance(point)
29
+ temp = self - point
30
+
31
+ Math::sqrt(temp.x * temp.x + temp.y * temp.y + temp.z * temp.z)
32
+ end
33
+
34
+ def midpoint(point)
35
+ Point.new((@x + point.x) * 0.5, (@y + point.y) * 0.5, (@z + point.z) * 0.5)
36
+ end
37
+
38
+ def to_ary
39
+ [@x, @y, @z]
40
+ end
41
+
42
+ def to_a
43
+ self.to_ary
44
+ end
45
+ end
46
+
47
+ # Class For Generating 2-D Shapes
48
+ class SimpleShape
49
+
50
+ end
51
+
52
+ # Class For Generating 3-D Shapes
53
+ class ComplexShape
54
+ # Generates an array of 3 component vertices in counter-clockwise triangle
55
+ # configuration. This is the vertex data for a 3 dimensional sphere. The
56
+ # num_rings parameter should always be 0 or a positive even number.
57
+ def self.gen_sphere(radius, num_rings)
58
+ points_per_ring = num_rings * 2 + 4
59
+ rings_per_half = num_rings / 2 + 1 # Count The Center Ring For Both Sides
60
+
61
+ # Generate Points From Bottom Of Sphere To The Top
62
+ points = []
63
+ for i in 1..num_rings + 1
64
+ ring_y_factor = (i - rings_per_half).to_f / rings_per_half
65
+ ring_y_value = ring_y_factor * radius
66
+ ring_radius = Math::cos(Math::asin(ring_y_value / radius)) * radius
67
+
68
+ for i in 0..points_per_ring
69
+ radians = Conversion.deg_to_rad(i.to_f / points_per_ring * 360)
70
+
71
+ x = Math::cos(radians) * ring_radius
72
+ z = Math::sin(radians) * ring_radius
73
+
74
+ points.push(Point.new(x, ring_y_value, z))
75
+ end
76
+ end
77
+
78
+ vertex_array, previous_points = [], []
79
+
80
+ # Build Bottom End-Cap
81
+ bottom_point = [0, -radius, 0]
82
+ for i in 0...points_per_ring
83
+ curr_vert = points[i]
84
+ next_vert = Util.overflow_wrap(points, i + 1)
85
+
86
+ vertex_array.push([next_vert.to_a, curr_vert.to_a, bottom_point])
87
+ previous_points.push(curr_vert)
88
+ end
89
+
90
+ # Build Intermediate Mesh
91
+ for i in points_per_ring...points.size
92
+ curr_vert = points[i]
93
+ next_vert = Util.overflow_wrap(points, i + 1)
94
+
95
+ last_curr_vert = previous_points[i % points_per_ring]
96
+ last_next_vert = Util.overflow_wrap(previous_points, (i % points_per_ring) + 1)
97
+
98
+ vertex_array.push([next_vert.to_a, curr_vert.to_a, last_curr_vert.to_a])
99
+ vertex_array.push([last_next_vert.to_a, next_vert.to_a, last_curr_vert.to_a])
100
+ previous_points[i % points_per_ring] = curr_vert
101
+ end
102
+
103
+ # Build Top End-Cap
104
+ top_point = [0, radius, 0]
105
+ for i in 0...previous_points.size()
106
+ curr_vert = previous_points[i]
107
+ next_vert = Util.overflow_wrap(previous_points, i + 1)
108
+
109
+ vertex_array.push([curr_vert.to_a, next_vert.to_a, top_point.to_a])
110
+ end
111
+
112
+ vertex_array.flatten!
113
+
114
+ vertex_array
115
+ end
116
+
117
+ # Generates an array of 3 component vertices in counter-clockwise triangle
118
+ # configuration. This is the vertex data for a 3 dimensional diamond. The
119
+ # girdle_facets parameters should always be an even number.
120
+ def self.gen_diamond(diamond_height, girdle_radius, girdle_facets)
121
+ # Table Y Value Is Equal To diamond_height
122
+ girdle_y_value = diamond_height * 2.5 / 3.0 # Girdle Upper Ring
123
+ crown_y_midpoint = 2.0 / 3.0
124
+
125
+ girdle_thickness = diamond_height / 10.0
126
+
127
+ table_radius = girdle_radius / 1.8
128
+ table_facets = girdle_facets / 2.0
129
+
130
+ girdle_points = []
131
+ girdle_point_factor = 360.0 / girdle_facets # Multiply With Point Index To Get Degree
132
+ # Generate x And z Values For Diamond Girdle
133
+ for i in 0...girdle_facets
134
+ curr_degree = i.to_f * girdle_point_factor
135
+ curr_rad = Conversion::deg_to_rad(curr_degree)
136
+
137
+ x = Math::cos(curr_rad) * girdle_radius
138
+ z = Math::sin(curr_rad) * girdle_radius
139
+
140
+ girdle_points.push(Point.new(x, girdle_y_value, z))
141
+ end
142
+
143
+ table_points = []
144
+ table_point_factor = 360.0 / table_facets # Multiply With Point Index To Get Degree
145
+ # Generate x And z Values For Diamond Table
146
+ for i in 0...table_facets
147
+ curr_degree = i.to_f * table_point_factor
148
+ curr_rad = Conversion::deg_to_rad(curr_degree)
149
+
150
+ x = Math::cos(curr_rad) * table_radius
151
+ z = Math::sin(curr_rad) * table_radius
152
+
153
+ table_points.push(Point.new(x, diamond_height, z))
154
+ end
155
+
156
+ vertex_array = []
157
+ # Traverse Every Other Point On The Girdle
158
+ for i in 0...girdle_points.size / 2
159
+ center_girdle_index = (i * 2) + 1
160
+ left_girdle_index = center_girdle_index - 1
161
+ right_girdle_index = center_girdle_index + 1
162
+
163
+ gird_center = girdle_points[center_girdle_index]
164
+ gird_left = girdle_points[left_girdle_index]
165
+ gird_right = Util.overflow_wrap(girdle_points, right_girdle_index)
166
+
167
+ tab_left = table_points[left_girdle_index / 2]
168
+ tab_right = Util.overflow_wrap(table_points, right_girdle_index / 2)
169
+
170
+ # Crown Triangles
171
+ # Using 3D Equation Of A Line To Get Central Connection Point For Crown
172
+ slope = tab_left.midpoint(tab_right) - gird_center
173
+ crown_midpoint = slope.scale(crown_y_midpoint) + gird_center
174
+
175
+ vertex_array.push([crown_midpoint.to_a, gird_left.to_a, gird_center.to_a])
176
+ vertex_array.push([crown_midpoint.to_a, gird_center.to_a, gird_right.to_a])
177
+
178
+ vertex_array.push([crown_midpoint.to_a, tab_left.to_a, gird_left.to_a])
179
+ vertex_array.push([crown_midpoint.to_a, gird_right.to_a, tab_right.to_a])
180
+
181
+ vertex_array.push([crown_midpoint.to_a, tab_right.to_a, tab_left.to_a])
182
+
183
+ # Girdle Triangles
184
+ lower_gird_center = Point.new(gird_center.x, gird_center.y - girdle_thickness, gird_center.z)
185
+ lower_gird_left = Point.new(gird_left.x, gird_left.y - girdle_thickness, gird_left.z)
186
+ lower_gird_right = Point.new(gird_right.x, gird_right.y - girdle_thickness, gird_right.z)
187
+
188
+ vertex_array.push([gird_center.to_a, gird_left.to_a, lower_gird_left.to_a])
189
+ vertex_array.push([gird_center.to_a, lower_gird_left.to_a, lower_gird_center.to_a])
190
+
191
+ vertex_array.push([gird_center.to_a, lower_gird_center.to_a, gird_right.to_a])
192
+ vertex_array.push([gird_right.to_a, lower_gird_center.to_a, lower_gird_right.to_a])
193
+
194
+ # Pavilion Triangles
195
+ pavil_bottom = Point.new(0, 0, 0)
196
+
197
+ vertex_array.push([lower_gird_center.to_a, lower_gird_left.to_a, pavil_bottom.to_a])
198
+ vertex_array.push([lower_gird_center.to_a, pavil_bottom.to_a, lower_gird_right.to_a])
199
+
200
+ # Table Triangles
201
+ table_mid = Point.new(0, diamond_height, 0)
202
+
203
+ vertex_array.push([table_mid.to_a, tab_left.to_a, tab_right.to_a])
204
+ end
205
+
206
+ vertex_array.flatten!
207
+
208
+ vertex_array
209
+ end
210
+ end
211
+
212
+ end
@@ -0,0 +1,301 @@
1
+
2
+ module RubyGL
3
+
4
+ class Conversion
5
+ @@PI_DIV = Math::PI / 180.0
6
+ @@DIV_PI = 180.0 / Math::PI
7
+
8
+ def self.deg_to_rad(degrees)
9
+ degrees * @@PI_DIV
10
+ end
11
+
12
+ def self.rad_to_deg(radians)
13
+ radians * @@DIV_PI
14
+ end
15
+ end
16
+
17
+ class Vec3
18
+ def initialize(array = nil)
19
+ @data = Array.new(3, 0)
20
+
21
+ if array then
22
+ for i in 0...@data.size
23
+ @data[i] = array[i]
24
+ end
25
+ end
26
+ end
27
+
28
+ def +(other_vector)
29
+ new_vector = Vec3.new()
30
+
31
+ for i in 0...@data.size
32
+ new_vector[i] = @data[i] + other_vector[i]
33
+ end
34
+
35
+ new_vector
36
+ end
37
+
38
+ def -(other_vector)
39
+ new_vector = Vec3.new()
40
+
41
+ for i in 0...@data.size
42
+ new_vector[i] = @data[i] - other_vector[i]
43
+ end
44
+
45
+ new_vector
46
+ end
47
+
48
+ def cross(other_vector)
49
+ new_vector = Vec3.new()
50
+
51
+ new_vector[0] = (@data[1] * other_vector[2]) - (@data[2] * other_vector[1])
52
+ new_vector[1] = (@data[0] * other_vector[2]) - (@data[2] * other_vector[0])
53
+ new_vector[2] = (@data[0] * other_vector[1]) - (@data[1] * other_vector[0])
54
+
55
+ new_vector
56
+ end
57
+
58
+ def norm!()
59
+ curr_len = self.len().abs()
60
+
61
+ for i in 0...@data.size
62
+ @data[i] /= curr_len
63
+ end
64
+ end
65
+
66
+ def norm()
67
+ new_vector = Vec2.new()
68
+
69
+ for i in 0...@data.size
70
+ new_vector[i] = @data[i]
71
+ end
72
+ new_vector.norm!
73
+
74
+ new_vector
75
+ end
76
+
77
+ def len()
78
+ sum = 0
79
+
80
+ for i in 0...@data.size
81
+ sum += @data[i] * @data[i]
82
+ end
83
+
84
+ Math::sqrt(sum)
85
+ end
86
+
87
+ def [](index)
88
+ @data[index]
89
+ end
90
+
91
+ def []=(index, value)
92
+ @data[index] = value
93
+ end
94
+
95
+ def to_ary()
96
+ Array.new(@data)
97
+ end
98
+
99
+ def to_a()
100
+ self.to_ary
101
+ end
102
+ end
103
+
104
+ class Vec4
105
+ def initialize()
106
+ @data = Array.new(4, 0)
107
+ end
108
+
109
+ def +(other_vector)
110
+ new_vector = Vec4.new()
111
+
112
+ for i in 0..@data.size
113
+ new_vector[i] = @data[i] + other_vector[i]
114
+ end
115
+
116
+ new_vector
117
+ end
118
+
119
+ def -(other_vector)
120
+ new_vector = Vec4.new()
121
+
122
+ for i in 0..@data.size
123
+ new_vector[i] = @data[i] - other_vector[i]
124
+ end
125
+
126
+ new_vector
127
+ end
128
+
129
+ def norm!()
130
+ curr_len = self.len()
131
+
132
+ for i in 0...@data.size
133
+ @data /= curr_len
134
+ end
135
+ end
136
+
137
+ def norm()
138
+ new_vector = Vec2.new()
139
+
140
+ for i in 0...@data.size
141
+ new_vector[i] = @data[i]
142
+ end
143
+ new_vector.norm!
144
+
145
+ new_vector
146
+ end
147
+
148
+ def len()
149
+ sum = 0
150
+
151
+ for i in 0...@data.size
152
+ sum += @data[i] * @data[i]
153
+ end
154
+
155
+ Math::sqrt(sum)
156
+ end
157
+
158
+ def [](index)
159
+ @data[index]
160
+ end
161
+
162
+ def []=(index, value)
163
+ @data[index] = value
164
+ end
165
+
166
+ def to_ary()
167
+ Array.new(@data)
168
+ end
169
+
170
+ def to_a()
171
+ self.to_ary
172
+ end
173
+ end
174
+
175
+ # Stored In Column Order For Interoperability With OpenGL. Subscript Operator
176
+ # Will Return A Vector That Represents A Column Within The Matrix. This Matrix
177
+ # Class Only Supports Matrices Where The Number Of Rows Equals The Number Of
178
+ # Columns; Operations Are Constrained As Such.
179
+ class Mat4
180
+ def initialize(diagonal = 1.0)
181
+ @data = Array.new(4) { |index|
182
+ column = Vec4.new()
183
+ column[index] = diagonal
184
+
185
+ column
186
+ }
187
+ end
188
+
189
+ def self.translation(x, y, z)
190
+ matrix = Mat4.new(1.0)
191
+
192
+ matrix[3][0] = x
193
+ matrix[3][1] = y
194
+ matrix[3][2] = z
195
+
196
+ matrix
197
+ end
198
+
199
+ # The axis value should be 0 if that axis should not be rotated around;
200
+ # any other value indicates its priority (higher priority axis is rotated
201
+ # around before the lower priority axis).
202
+ def self.rotation(x_axis, y_axis, z_axis, theta)
203
+ rad_angle = Conversion::deg_to_rad(theta)
204
+ sin_angle = Math::sin(rad_angle)
205
+ cos_angle = Math::cos(rad_angle)
206
+
207
+ # Multiply Lower -> Higher To Get Ordering Correct
208
+ axis_priority = [[:x, x_axis], [:y, y_axis], [:z, z_axis]]
209
+ axis_priority.delete_if { |(_, val)|
210
+ val == 0
211
+ }.sort!.reverse!
212
+
213
+ rot_matrix = Mat4.new(1.0)
214
+ axis_priority.each { |(axis, _)|
215
+ mat = Mat4.new(1.0)
216
+
217
+ if axis == :x then
218
+ mat[1][1] = mat[2][2] = cos_angle
219
+ mat[1][2] = sin_angle
220
+ mat[2][1] = -sin_angle
221
+ elsif axis == :y then
222
+ mat[0][0] = mat[2][2] = cos_angle
223
+ mat[0][2] = -sin_angle
224
+ mat[2][0] = sin_angle
225
+ else
226
+ mat[0][0] = mat[1][1] = cos_angle
227
+ mat[0][1] = sin_angle
228
+ mat[1][0] = -sin_angle
229
+ end
230
+
231
+ rot_matrix *= mat
232
+ }
233
+
234
+ rot_matrix
235
+ end
236
+
237
+ def self.perspective(fov, aspect, z_near, z_far)
238
+ top = Math::tan(Conversion::deg_to_rad(fov) / 2) * z_near
239
+ right = top * aspect
240
+
241
+ mat = Mat4.new(1.0)
242
+ mat[0][0] = z_near / right
243
+ mat[1][1] = z_near / top
244
+ mat[2][2] = -(z_far + z_near) / (z_far - z_near)
245
+ mat[3][2] = -2.0 * z_far * z_near / (z_far - z_near)
246
+ mat[2][3] = -1.0
247
+
248
+ mat
249
+ end
250
+
251
+ def self.orthogonal(left, right, bottom, top, z_near = -1.0, z_far = 1.0)
252
+ mat = Mat4.new(1.0)
253
+ mat[0][0] = 2.0 / (right - left)
254
+ mat[1][1] = 2.0 / (top - bottom)
255
+ mat[2][2] = 2.0 / (z_near - z_far)
256
+ mat[3][3] = 1.0
257
+ mat[3][0] = -(right + left) / (right - left)
258
+ mat[3][1] = -(top + bottom) / (top - bottom)
259
+ mat[3][2] = -(z_far + z_near) / (z_far - z_near)
260
+
261
+ mat
262
+ end
263
+
264
+ def *(other_matrix)
265
+ new_matrix = Mat4.new(0)
266
+
267
+ for i in 0...self.dim
268
+ for j in 0...self.dim
269
+ for k in 0...self.dim
270
+ new_matrix[j][i] += self[k][i] * other_matrix[j][k]
271
+ end
272
+ end
273
+ end
274
+
275
+ new_matrix
276
+ end
277
+
278
+ def dim()
279
+ @data.size()
280
+ end
281
+
282
+ def [](index)
283
+ @data[index]
284
+ end
285
+
286
+ def []=(index, value)
287
+ @data[index] = value
288
+ end
289
+
290
+ def to_ary()
291
+ @data.collect { |vec|
292
+ vec.to_ary
293
+ }.flatten!
294
+ end
295
+
296
+ def to_a()
297
+ self.to_ary
298
+ end
299
+ end
300
+
301
+ end