cyberarm_engine 0.12.0 → 0.15.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 +4 -4
- data/.rubocop.yml +8 -0
- data/Gemfile +1 -1
- data/README.md +33 -3
- data/Rakefile +1 -1
- data/assets/textures/default.png +0 -0
- data/cyberarm_engine.gemspec +11 -8
- data/lib/cyberarm_engine.rb +24 -4
- data/lib/cyberarm_engine/animator.rb +56 -0
- data/lib/cyberarm_engine/background.rb +19 -15
- data/lib/cyberarm_engine/background_nine_slice.rb +125 -0
- data/lib/cyberarm_engine/bounding_box.rb +18 -18
- data/lib/cyberarm_engine/cache.rb +4 -0
- data/lib/cyberarm_engine/cache/download_manager.rb +121 -0
- data/lib/cyberarm_engine/common.rb +16 -16
- data/lib/cyberarm_engine/config_file.rb +46 -0
- data/lib/cyberarm_engine/game_object.rb +63 -72
- data/lib/cyberarm_engine/game_state.rb +7 -4
- data/lib/cyberarm_engine/model.rb +207 -0
- data/lib/cyberarm_engine/model/material.rb +21 -0
- data/lib/cyberarm_engine/model/model_object.rb +131 -0
- data/lib/cyberarm_engine/model/parser.rb +74 -0
- data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -0
- data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -0
- data/lib/cyberarm_engine/model_cache.rb +31 -0
- data/lib/cyberarm_engine/opengl.rb +28 -0
- data/lib/cyberarm_engine/opengl/light.rb +50 -0
- data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -0
- data/lib/cyberarm_engine/opengl/perspective_camera.rb +38 -0
- data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -0
- data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +164 -0
- data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +289 -0
- data/lib/cyberarm_engine/opengl/renderer/renderer.rb +22 -0
- data/lib/cyberarm_engine/opengl/shader.rb +406 -0
- data/lib/cyberarm_engine/opengl/texture.rb +69 -0
- data/lib/cyberarm_engine/ray.rb +5 -5
- data/lib/cyberarm_engine/stats.rb +21 -0
- data/lib/cyberarm_engine/text.rb +45 -31
- data/lib/cyberarm_engine/timer.rb +1 -1
- data/lib/cyberarm_engine/transform.rb +221 -9
- data/lib/cyberarm_engine/ui/border_canvas.rb +4 -3
- data/lib/cyberarm_engine/ui/dsl.rb +68 -50
- data/lib/cyberarm_engine/ui/element.rb +57 -18
- data/lib/cyberarm_engine/ui/elements/button.rb +86 -16
- data/lib/cyberarm_engine/ui/elements/check_box.rb +24 -32
- data/lib/cyberarm_engine/ui/elements/container.rb +88 -24
- data/lib/cyberarm_engine/ui/elements/edit_box.rb +179 -0
- data/lib/cyberarm_engine/ui/elements/edit_line.rb +180 -27
- data/lib/cyberarm_engine/ui/elements/flow.rb +1 -3
- data/lib/cyberarm_engine/ui/elements/image.rb +12 -9
- data/lib/cyberarm_engine/ui/elements/label.rb +96 -15
- data/lib/cyberarm_engine/ui/elements/list_box.rb +68 -0
- data/lib/cyberarm_engine/ui/elements/progress.rb +6 -5
- data/lib/cyberarm_engine/ui/elements/radio.rb +6 -0
- data/lib/cyberarm_engine/ui/elements/slider.rb +104 -0
- data/lib/cyberarm_engine/ui/elements/stack.rb +1 -3
- data/lib/cyberarm_engine/ui/elements/toggle_button.rb +40 -31
- data/lib/cyberarm_engine/ui/event.rb +8 -7
- data/lib/cyberarm_engine/ui/gui_state.rb +89 -6
- data/lib/cyberarm_engine/ui/style.rb +10 -9
- data/lib/cyberarm_engine/ui/theme.rb +39 -21
- data/lib/cyberarm_engine/vector.rb +132 -38
- data/lib/cyberarm_engine/version.rb +2 -2
- data/lib/cyberarm_engine/{engine.rb → window.rb} +30 -19
- metadata +87 -16
- data/lib/cyberarm_engine/shader.rb +0 -205
@@ -0,0 +1,69 @@
|
|
1
|
+
module CyberarmEngine
|
2
|
+
class Texture
|
3
|
+
DEFAULT_TEXTURE = "#{CYBERARM_ENGINE_ROOT_PATH}/assets/textures/default.png".freeze
|
4
|
+
|
5
|
+
CACHE = {}
|
6
|
+
|
7
|
+
def self.release_textures
|
8
|
+
CACHE.values.each do |id|
|
9
|
+
glDeleteTextures(id)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.from_cache(path, retro)
|
14
|
+
CACHE.dig("#{path}?retro=#{retro}")
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :id
|
18
|
+
|
19
|
+
def initialize(path: nil, image: nil, retro: false)
|
20
|
+
raise "keyword :path or :image must be provided!" if path.nil? && image.nil?
|
21
|
+
|
22
|
+
@retro = retro
|
23
|
+
@path = path
|
24
|
+
|
25
|
+
if @path
|
26
|
+
unless File.exist?(@path)
|
27
|
+
warn "Missing texture at: #{@path}"
|
28
|
+
@retro = true # override retro setting
|
29
|
+
@path = DEFAULT_TEXTURE
|
30
|
+
end
|
31
|
+
|
32
|
+
if texture = Texture.from_cache(@path, @retro)
|
33
|
+
@id = texture.id
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
image = load_image(@path)
|
38
|
+
@id = create_from_image(image)
|
39
|
+
else
|
40
|
+
@id = create_from_image(image)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def load_image(path)
|
45
|
+
CACHE["#{path}?retro=#{@retro}"] = self
|
46
|
+
Gosu::Image.new(path, retro: @retro)
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_from_image(image)
|
50
|
+
array_of_pixels = image.to_blob
|
51
|
+
|
52
|
+
tex_names_buf = " " * 4
|
53
|
+
glGenTextures(1, tex_names_buf)
|
54
|
+
texture_id = tex_names_buf.unpack1("L2")
|
55
|
+
|
56
|
+
glBindTexture(GL_TEXTURE_2D, texture_id)
|
57
|
+
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, array_of_pixels)
|
58
|
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
|
59
|
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
|
60
|
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) if @retro
|
61
|
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) unless @retro
|
62
|
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
|
63
|
+
glGenerateMipmap(GL_TEXTURE_2D)
|
64
|
+
gl_error?
|
65
|
+
|
66
|
+
texture_id
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/cyberarm_engine/ray.rb
CHANGED
@@ -4,7 +4,7 @@ module CyberarmEngine
|
|
4
4
|
raise "Origin must be a Vector!" unless origin.is_a?(Vector)
|
5
5
|
raise "Direction must be a Vector!" unless direction.is_a?(Vector)
|
6
6
|
|
7
|
-
@origin
|
7
|
+
@origin = origin
|
8
8
|
@direction = direction
|
9
9
|
@range = range
|
10
10
|
|
@@ -42,15 +42,15 @@ module CyberarmEngine
|
|
42
42
|
tmin = max(tmin, min(tz1, tz2))
|
43
43
|
tmax = min(tmax, max(tz1, tz2))
|
44
44
|
|
45
|
-
|
45
|
+
tmax >= max(tmin, 0.0)
|
46
46
|
end
|
47
47
|
|
48
48
|
def min(x, y)
|
49
|
-
((x) < (y) ?
|
49
|
+
((x) < (y) ? x : y)
|
50
50
|
end
|
51
51
|
|
52
52
|
def max(x, y)
|
53
|
-
((x) > (y) ?
|
53
|
+
((x) > (y) ? x : y)
|
54
54
|
end
|
55
55
|
end
|
56
|
-
end
|
56
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module CyberarmEngine
|
2
|
+
class Stats
|
3
|
+
@@hash = {
|
4
|
+
gui_recalculations_last_frame: 0
|
5
|
+
}
|
6
|
+
|
7
|
+
def self.get(key)
|
8
|
+
@@hash.dig(key)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.increment(key, n)
|
12
|
+
@@hash[key] += n
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.clear
|
16
|
+
@@hash.each do |key, _value|
|
17
|
+
@@hash[key] = 0
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/cyberarm_engine/text.rb
CHANGED
@@ -5,39 +5,40 @@ module CyberarmEngine
|
|
5
5
|
attr_accessor :x, :y, :z, :size, :options
|
6
6
|
attr_reader :text, :textobject, :factor_x, :factor_y, :color, :shadow, :shadow_size, :shadow_alpha, :shadow_color
|
7
7
|
|
8
|
-
def initialize(text, options={})
|
8
|
+
def initialize(text, options = {})
|
9
9
|
@text = text.to_s || ""
|
10
10
|
@options = options
|
11
11
|
@size = options[:size] || 18
|
12
|
-
@font = options[:font] ||
|
12
|
+
@font = options[:font] || Gosu.default_font_name
|
13
13
|
@x = options[:x] || 0
|
14
14
|
@y = options[:y] || 0
|
15
15
|
@z = options[:z] || 1025
|
16
16
|
@factor_x = options[:factor_x] || 1
|
17
17
|
@factor_y = options[:factor_y] || 1
|
18
18
|
@color = options[:color] || Gosu::Color::WHITE
|
19
|
-
@
|
19
|
+
@mode = options[:mode] || :default
|
20
|
+
@alignment = options[:alignment] || nil
|
20
21
|
@shadow = true if options[:shadow] == true
|
21
22
|
@shadow = false if options[:shadow] == false
|
22
|
-
@shadow = true if options[:shadow]
|
23
|
-
@shadow_size = options[:shadow_size]
|
24
|
-
@shadow_alpha= options[:shadow_alpha]
|
25
|
-
@shadow_alpha= options[:shadow_alpha]
|
26
|
-
@shadow_color= options[:shadow_color]
|
23
|
+
@shadow = true if options[:shadow].nil?
|
24
|
+
@shadow_size = options[:shadow_size] || 1
|
25
|
+
@shadow_alpha = options[:shadow_alpha] || 30
|
26
|
+
@shadow_alpha = options[:shadow_alpha] || 30
|
27
|
+
@shadow_color = options[:shadow_color]
|
27
28
|
@textobject = check_cache(@size, @font)
|
28
29
|
|
29
30
|
if @alignment
|
30
31
|
case @alignment
|
31
32
|
when :left
|
32
|
-
@x = 0+BUTTON_PADDING
|
33
|
+
@x = 0 + BUTTON_PADDING
|
33
34
|
when :center
|
34
|
-
@x = ($window.width/2)-(@textobject.text_width(@text)/2)
|
35
|
+
@x = ($window.width / 2) - (@textobject.text_width(@text) / 2)
|
35
36
|
when :right
|
36
|
-
@x = $window.width-BUTTON_PADDING
|
37
|
+
@x = $window.width - BUTTON_PADDING - @textobject.text_width(@text)
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
+
self
|
41
42
|
end
|
42
43
|
|
43
44
|
def check_cache(size, font_name)
|
@@ -61,7 +62,7 @@ module CyberarmEngine
|
|
61
62
|
CACHE[@size][@font] = font
|
62
63
|
end
|
63
64
|
|
64
|
-
|
65
|
+
font
|
65
66
|
end
|
66
67
|
|
67
68
|
def text=(string)
|
@@ -73,64 +74,76 @@ module CyberarmEngine
|
|
73
74
|
@rendered_shadow = nil
|
74
75
|
@factor_x = n
|
75
76
|
end
|
77
|
+
|
76
78
|
def factor_y=(n)
|
77
79
|
@rendered_shadow = nil
|
78
80
|
@factor_y = n
|
79
81
|
end
|
82
|
+
|
80
83
|
def color=(color)
|
81
84
|
@rendered_shadow = nil
|
82
85
|
@color = color
|
83
86
|
end
|
87
|
+
|
84
88
|
def shadow=(boolean)
|
85
89
|
@rendered_shadow = nil
|
86
90
|
@shadow = boolean
|
87
91
|
end
|
92
|
+
|
88
93
|
def shadow_size=(n)
|
89
94
|
@rendered_shadow = nil
|
90
95
|
@shadow_size = n
|
91
96
|
end
|
97
|
+
|
92
98
|
def shadow_alpha=(n)
|
93
99
|
@rendered_shadow = nil
|
94
100
|
@shadow_alpha = n
|
95
101
|
end
|
102
|
+
|
96
103
|
def shadow_color=(n)
|
97
104
|
@rendered_shadow = nil
|
98
105
|
@shadow_color = n
|
99
106
|
end
|
100
107
|
|
101
|
-
def width
|
102
|
-
textobject.text_width(
|
108
|
+
def width(text = @text)
|
109
|
+
textobject.text_width(text)
|
110
|
+
end
|
111
|
+
|
112
|
+
def markup_width(text = @text)
|
113
|
+
textobject.markup_width(text)
|
103
114
|
end
|
104
115
|
|
105
|
-
def height
|
106
|
-
|
116
|
+
def height(text = @text)
|
117
|
+
text.lines.count > 0 ? text.lines.count * textobject.height : @textobject.height
|
107
118
|
end
|
108
119
|
|
109
|
-
def draw
|
120
|
+
def draw(method = :draw_markup)
|
110
121
|
if @shadow && !ARGV.join.include?("--no-shadow")
|
111
122
|
shadow_alpha = @color.alpha <= 30 ? @color.alpha : @shadow_alpha
|
112
|
-
shadow_color = @shadow_color
|
123
|
+
shadow_color = @shadow_color || Gosu::Color.rgba(@color.red, @color.green, @color.blue,
|
124
|
+
shadow_alpha)
|
125
|
+
white = Gosu::Color::WHITE
|
113
126
|
|
114
127
|
_x = @shadow_size
|
115
128
|
_y = @shadow_size
|
116
129
|
|
117
|
-
@rendered_shadow ||= Gosu.render((
|
118
|
-
@textobject.
|
119
|
-
@textobject.
|
130
|
+
@rendered_shadow ||= Gosu.render((width + (shadow_size * 2)).ceil, (height + (@shadow_size * 2)).ceil) do
|
131
|
+
@textobject.send(method, @text, _x - @shadow_size, _y, @z, @factor_x, @factor_y, white, :add)
|
132
|
+
@textobject.send(method, @text, _x - @shadow_size, _y - @shadow_size, @z, @factor_x, @factor_y, white, :add)
|
120
133
|
|
121
|
-
@textobject.
|
122
|
-
@textobject.
|
134
|
+
@textobject.send(method, @text, _x, _y - @shadow_size, @z, @factor_x, @factor_y, white, :add)
|
135
|
+
@textobject.send(method, @text, _x + @shadow_size, _y - @shadow_size, @z, @factor_x, @factor_y, white, :add)
|
123
136
|
|
124
|
-
@textobject.
|
125
|
-
@textobject.
|
137
|
+
@textobject.send(method, @text, _x, _y + @shadow_size, @z, @factor_x, @factor_y, white, :add)
|
138
|
+
@textobject.send(method, @text, _x - @shadow_size, _y + @shadow_size, @z, @factor_x, @factor_y, white, :add)
|
126
139
|
|
127
|
-
@textobject.
|
128
|
-
@textobject.
|
140
|
+
@textobject.send(method, @text, _x + @shadow_size, _y, @z, @factor_x, @factor_y, white, :add)
|
141
|
+
@textobject.send(method, @text, _x + @shadow_size, _y + @shadow_size, @z, @factor_x, @factor_y, white, :add)
|
129
142
|
end
|
130
|
-
@rendered_shadow.draw(@x
|
143
|
+
@rendered_shadow.draw(@x - @shadow_size, @y - @shadow_size, @z, @factor_x, @factor_y, shadow_color)
|
131
144
|
end
|
132
145
|
|
133
|
-
@textobject.
|
146
|
+
@textobject.send(method, @text, @x, @y, @z, @factor_x, @factor_y, @color, @mode)
|
134
147
|
end
|
135
148
|
|
136
149
|
def alpha=(n)
|
@@ -141,6 +154,7 @@ module CyberarmEngine
|
|
141
154
|
@color.alpha
|
142
155
|
end
|
143
156
|
|
144
|
-
def update
|
157
|
+
def update
|
158
|
+
end
|
145
159
|
end
|
146
160
|
end
|
@@ -1,20 +1,37 @@
|
|
1
1
|
module CyberarmEngine
|
2
|
+
# Basic 4x4 matrix operations
|
2
3
|
class Transform
|
3
4
|
attr_reader :elements
|
5
|
+
|
4
6
|
def initialize(matrix)
|
5
7
|
@elements = matrix
|
6
8
|
|
7
9
|
raise "Transform is wrong size! Got #{@elements.size}, expected 16" if 16 != @elements.size
|
10
|
+
raise "Invalid value for matrix, must all be numeric!" if @elements.any? { |e| e.nil? || !e.is_a?(Numeric) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.identity
|
14
|
+
Transform.new(
|
15
|
+
[
|
16
|
+
1, 0, 0, 0,
|
17
|
+
0, 1, 0, 0,
|
18
|
+
0, 0, 1, 0,
|
19
|
+
0, 0, 0, 1
|
20
|
+
]
|
21
|
+
)
|
8
22
|
end
|
9
23
|
|
24
|
+
### 2D Operations meant for interacting with Gosu ###
|
25
|
+
|
26
|
+
# 2d rotate operation, replicates Gosu's Gosu.rotate function
|
10
27
|
def self.rotate(angle, rotate_around = nil)
|
11
28
|
double c = Math.cos(angle).degrees_to_radians
|
12
29
|
double s = Math.sin(angle).degrees_to_radians
|
13
30
|
matrix = [
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
31
|
+
+c, +s, 0, 0,
|
32
|
+
-s, +c, 0, 0,
|
33
|
+
0, 0, 1, 0,
|
34
|
+
0, 0, 0, 1
|
18
35
|
]
|
19
36
|
|
20
37
|
rotate_matrix = Transform.new(matrix, rows: 4, columns: 4)
|
@@ -28,28 +45,30 @@ module CyberarmEngine
|
|
28
45
|
)
|
29
46
|
end
|
30
47
|
|
31
|
-
|
48
|
+
rotate_matrix
|
32
49
|
end
|
33
50
|
|
51
|
+
# 2d translate operation, replicates Gosu's Gosu.translate function
|
34
52
|
def self.translate(vector)
|
35
53
|
x, y, z = vector.to_a[0..2]
|
36
54
|
matrix = [
|
37
55
|
1, 0, 0, 0,
|
38
56
|
0, 1, 0, 0,
|
39
57
|
0, 0, 1, 0,
|
40
|
-
x, y, z, 1
|
58
|
+
x, y, z, 1
|
41
59
|
]
|
42
60
|
|
43
61
|
Transform.new(matrix)
|
44
62
|
end
|
45
63
|
|
64
|
+
# 2d scale operation, replicates Gosu's Gosu.rotate function
|
46
65
|
def self.scale(vector, center_around = nil)
|
47
66
|
scale_x, scale_y, scale_z = vector.to_a[0..2]
|
48
67
|
matrix = [
|
49
68
|
scale_x, 0, 0, 0,
|
50
69
|
0, scale_y, 0, 0,
|
51
70
|
0, 0, scale_z, 0,
|
52
|
-
0, 0, 0, 1
|
71
|
+
0, 0, 0, 1
|
53
72
|
]
|
54
73
|
|
55
74
|
scale_matrix = Transform.new(matrix)
|
@@ -63,7 +82,7 @@ module CyberarmEngine
|
|
63
82
|
)
|
64
83
|
end
|
65
84
|
|
66
|
-
|
85
|
+
scale_matrix
|
67
86
|
end
|
68
87
|
|
69
88
|
def self.concat(left, right)
|
@@ -80,5 +99,198 @@ module CyberarmEngine
|
|
80
99
|
|
81
100
|
Transform.new(matrix)
|
82
101
|
end
|
102
|
+
|
103
|
+
#### 3D Operations meant for OpenGL ###
|
104
|
+
|
105
|
+
def self.translate_3d(vector)
|
106
|
+
x, y, z = vector.to_a[0..2]
|
107
|
+
matrix = [
|
108
|
+
1, 0, 0, x,
|
109
|
+
0, 1, 0, y,
|
110
|
+
0, 0, 1, z,
|
111
|
+
0, 0, 0, 1
|
112
|
+
]
|
113
|
+
|
114
|
+
Transform.new(matrix)
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.rotate_3d(vector, _order = "zyx")
|
118
|
+
x, y, z = vector.to_a[0..2].map { |axis| axis * Math::PI / 180.0 }
|
119
|
+
|
120
|
+
rotation_x = Transform.new(
|
121
|
+
[
|
122
|
+
1, 0, 0, 0,
|
123
|
+
0, Math.cos(x), -Math.sin(x), 0,
|
124
|
+
0, Math.sin(x), Math.cos(x), 0,
|
125
|
+
0, 0, 0, 1
|
126
|
+
]
|
127
|
+
)
|
128
|
+
|
129
|
+
rotation_y = Transform.new(
|
130
|
+
[
|
131
|
+
Math.cos(y), 0, Math.sin(y), 0,
|
132
|
+
0, 1, 0, 0,
|
133
|
+
-Math.sin(y), 0, Math.cos(y), 0,
|
134
|
+
0, 0, 0, 1
|
135
|
+
]
|
136
|
+
)
|
137
|
+
|
138
|
+
rotation_z = Transform.new(
|
139
|
+
[
|
140
|
+
Math.cos(z), -Math.sin(z), 0, 0,
|
141
|
+
Math.sin(z), Math.cos(z), 0, 0,
|
142
|
+
0, 0, 1, 0,
|
143
|
+
0, 0, 0, 1
|
144
|
+
]
|
145
|
+
)
|
146
|
+
|
147
|
+
rotation_z * rotation_y * rotation_x
|
148
|
+
end
|
149
|
+
|
150
|
+
# Implements glRotatef
|
151
|
+
# https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRotate.xml
|
152
|
+
def self.rotate_gl(angle, axis)
|
153
|
+
radians = angle * Math::PI / 180.0
|
154
|
+
s = Math.sin(radians)
|
155
|
+
c = Math.cos(radians)
|
156
|
+
|
157
|
+
axis = axis.normalized
|
158
|
+
x, y, z = axis.to_a[0..2]
|
159
|
+
|
160
|
+
n = (1.0 - c)
|
161
|
+
|
162
|
+
Transform.new(
|
163
|
+
[
|
164
|
+
x * x * n + c, x * y * n - z * s, x * z * n + y * s, 0,
|
165
|
+
y * x * n + z * s, y * y * n + c, y * z * n - x * s, 0,
|
166
|
+
x * z * n - y * s, y * z * n + x * s, z * z * n + c, 0,
|
167
|
+
0, 0, 0, 1.0
|
168
|
+
]
|
169
|
+
)
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.scale_3d(vector)
|
173
|
+
x, y, z = vector.to_a[0..2]
|
174
|
+
|
175
|
+
Transform.new(
|
176
|
+
[
|
177
|
+
x, 0, 0, 0,
|
178
|
+
0, y, 0, 0,
|
179
|
+
0, 0, z, 0,
|
180
|
+
0, 0, 0, 1
|
181
|
+
]
|
182
|
+
)
|
183
|
+
end
|
184
|
+
|
185
|
+
def self.perspective(fov_y, aspect_ratio, near, far)
|
186
|
+
f = 1.0 / Math.tan(fov_y.degrees_to_radians / 2.0) # cotangent
|
187
|
+
zn = (far + near.to_f) / (near - far.to_f)
|
188
|
+
zf = (2.0 * far * near.to_f) / (near - far.to_f)
|
189
|
+
|
190
|
+
Transform.new(
|
191
|
+
[
|
192
|
+
f / aspect_ratio, 0.0, 0.0, 0.0,
|
193
|
+
0.0, f, 0.0, 0.0,
|
194
|
+
0.0, 0.0, zn, zf,
|
195
|
+
0.0, 0.0, -1.0, 0.0
|
196
|
+
]
|
197
|
+
)
|
198
|
+
end
|
199
|
+
|
200
|
+
def self.orthographic(left, right, bottom, top, near, far)
|
201
|
+
s = Vector.new(
|
202
|
+
2 / (right - left.to_f),
|
203
|
+
2 / (top - bottom.to_f),
|
204
|
+
-2 / (far - near.to_f)
|
205
|
+
)
|
206
|
+
|
207
|
+
t = Vector.new(
|
208
|
+
(right + left.to_f) / (right - left.to_f),
|
209
|
+
(top + bottom.to_f) / (top - bottom.to_f),
|
210
|
+
(far + near.to_f) / (far - near.to_f)
|
211
|
+
)
|
212
|
+
|
213
|
+
Transform.new(
|
214
|
+
[
|
215
|
+
s.x, 0.0, 0.0, t.x,
|
216
|
+
0.0, s.y, 0.0, t.y,
|
217
|
+
0.0, 0.0, s.z, t.z,
|
218
|
+
0.0, 0.0, 0.0, 1.0
|
219
|
+
]
|
220
|
+
)
|
221
|
+
end
|
222
|
+
|
223
|
+
def self.view(eye, orientation)
|
224
|
+
# https://www.3dgep.com/understanding-the-view-matrix/#The_View_Matrix
|
225
|
+
cosPitch = Math.cos(orientation.z * Math::PI / 180.0)
|
226
|
+
sinPitch = Math.sin(orientation.z * Math::PI / 180.0)
|
227
|
+
cosYaw = Math.cos(orientation.y * Math::PI / 180.0)
|
228
|
+
sinYaw = Math.sin(orientation.y * Math::PI / 180.0)
|
229
|
+
|
230
|
+
x_axis = Vector.new(cosYaw, 0, -sinYaw)
|
231
|
+
y_axis = Vector.new(sinYaw * sinPitch, cosPitch, cosYaw * sinPitch)
|
232
|
+
z_axis = Vector.new(sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw)
|
233
|
+
|
234
|
+
Transform.new(
|
235
|
+
[
|
236
|
+
x_axis.x, y_axis.y, z_axis.z, 0,
|
237
|
+
x_axis.x, y_axis.y, z_axis.z, 0,
|
238
|
+
x_axis.x, y_axis.y, z_axis.z, 0,
|
239
|
+
-x_axis.dot(eye), -y_axis.dot(eye), -z_axis.dot(eye), 1
|
240
|
+
]
|
241
|
+
)
|
242
|
+
end
|
243
|
+
|
244
|
+
def *(other)
|
245
|
+
case other
|
246
|
+
when CyberarmEngine::Vector
|
247
|
+
matrix = @elements.clone
|
248
|
+
list = other.to_a
|
249
|
+
|
250
|
+
@elements.each_with_index do |e, i|
|
251
|
+
matrix[i] = e + list[i % 4]
|
252
|
+
end
|
253
|
+
|
254
|
+
Transform.new(matrix)
|
255
|
+
|
256
|
+
when CyberarmEngine::Transform
|
257
|
+
multiply_matrices(other)
|
258
|
+
else
|
259
|
+
p other.class
|
260
|
+
raise TypeError, "Expected CyberarmEngine::Vector or CyberarmEngine::Transform got #{other.class}"
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def get(x, y)
|
265
|
+
width = 4
|
266
|
+
|
267
|
+
# puts "Transform|#{self.object_id} -> #{@elements[width * y + x].inspect} (index: #{width * y + x})"
|
268
|
+
@elements[width * y + x]
|
269
|
+
end
|
270
|
+
|
271
|
+
def multiply_matrices(other)
|
272
|
+
matrix = Array.new(16, 0)
|
273
|
+
|
274
|
+
4.times do |x|
|
275
|
+
4.times do |y|
|
276
|
+
4.times do |k|
|
277
|
+
matrix[4 * y + x] += get(x, k) * other.get(k, y)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
Transform.new(matrix)
|
283
|
+
end
|
284
|
+
|
285
|
+
# arranges Matrix in column major form
|
286
|
+
def to_gl
|
287
|
+
e = @elements
|
288
|
+
[
|
289
|
+
e[0], e[4], e[8], e[12],
|
290
|
+
e[1], e[5], e[9], e[13],
|
291
|
+
e[2], e[6], e[10], e[14],
|
292
|
+
e[3], e[7], e[11], e[15]
|
293
|
+
]
|
294
|
+
end
|
83
295
|
end
|
84
|
-
end
|
296
|
+
end
|