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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/Rakefile +83 -0
- data/RubyGL.gemspec +23 -0
- data/bin/ffi_code_gen.rb +167 -0
- data/bin/gl_code_gen.rb +459 -0
- data/examples/faceted_example.rb +65 -0
- data/examples/instanced_example.rb +128 -0
- data/examples/phong_example.rb +72 -0
- data/ext/windows/RubyGL.so +0 -0
- data/ext/windows/SDL2.dll +0 -0
- data/lib/RubyGL/Native/glcontext.rb +48 -0
- data/lib/RubyGL/Native/include/GLContext.h +37 -0
- data/lib/RubyGL/Native/include/Input.h +16 -0
- data/lib/RubyGL/Native/include/Window.h +28 -0
- data/lib/RubyGL/Native/input.rb +13 -0
- data/lib/RubyGL/Native/opengl.rb +2032 -0
- data/lib/RubyGL/Native/src/GLContext.c +73 -0
- data/lib/RubyGL/Native/src/Input.c +26 -0
- data/lib/RubyGL/Native/src/Window.c +58 -0
- data/lib/RubyGL/Native/window.rb +25 -0
- data/lib/RubyGL/callback.rb +10 -0
- data/lib/RubyGL/geometry.rb +212 -0
- data/lib/RubyGL/math.rb +301 -0
- data/lib/RubyGL/memory.rb +122 -0
- data/lib/RubyGL/setup.rb +51 -0
- data/lib/RubyGL/shader.rb +203 -0
- data/lib/RubyGL/util.rb +77 -0
- data/lib/rubygl.rb +48 -0
- metadata +92 -0
@@ -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,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
|
data/lib/RubyGL/math.rb
ADDED
@@ -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
|