3rb 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.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/3rb.gemspec +29 -0
  4. data/CHANGELOG.md +12 -0
  5. data/LICENSE +21 -0
  6. data/README.md +321 -0
  7. data/Rakefile +13 -0
  8. data/examples/01_hello_cube.rb +29 -0
  9. data/examples/02_basic_geometries.rb +56 -0
  10. data/examples/03_materials.rb +61 -0
  11. data/examples/04_lighting.rb +63 -0
  12. data/examples/05_animation.rb +79 -0
  13. data/examples/06_custom_shader.rb +92 -0
  14. data/examples/07_scene_graph.rb +74 -0
  15. data/examples/08_orbit_controls.rb +50 -0
  16. data/examples/09_3d_chart.rb +71 -0
  17. data/examples/10_procedural_terrain.rb +140 -0
  18. data/examples/11_particle_system.rb +68 -0
  19. data/examples/12_model_loader.rb +73 -0
  20. data/examples/13_game_prototype.rb +145 -0
  21. data/examples/14_utah_teapot.rb +291 -0
  22. data/examples/15_stanford_bunny.rb +200 -0
  23. data/examples/16_cornell_box.rb +373 -0
  24. data/examples/17_weird_fractal4.rb +130 -0
  25. data/examples/18_platonic_solids.rb +268 -0
  26. data/lib/3rb/animation/animation_clip.rb +287 -0
  27. data/lib/3rb/animation/animation_mixer.rb +366 -0
  28. data/lib/3rb/cameras/camera.rb +50 -0
  29. data/lib/3rb/cameras/orthographic_camera.rb +92 -0
  30. data/lib/3rb/cameras/perspective_camera.rb +103 -0
  31. data/lib/3rb/controls/orbit_controls.rb +341 -0
  32. data/lib/3rb/core/buffer_attribute.rb +172 -0
  33. data/lib/3rb/core/group.rb +9 -0
  34. data/lib/3rb/core/object3d.rb +298 -0
  35. data/lib/3rb/core/scene.rb +78 -0
  36. data/lib/3rb/dsl/helpers.rb +57 -0
  37. data/lib/3rb/dsl/scene_builder.rb +288 -0
  38. data/lib/3rb/ffi/glfw.rb +61 -0
  39. data/lib/3rb/ffi/opengl.rb +137 -0
  40. data/lib/3rb/ffi/platform.rb +65 -0
  41. data/lib/3rb/geometries/box_geometry.rb +101 -0
  42. data/lib/3rb/geometries/buffer_geometry.rb +345 -0
  43. data/lib/3rb/geometries/cone_geometry.rb +29 -0
  44. data/lib/3rb/geometries/cylinder_geometry.rb +149 -0
  45. data/lib/3rb/geometries/plane_geometry.rb +75 -0
  46. data/lib/3rb/geometries/sphere_geometry.rb +93 -0
  47. data/lib/3rb/geometries/torus_geometry.rb +77 -0
  48. data/lib/3rb/lights/ambient_light.rb +9 -0
  49. data/lib/3rb/lights/directional_light.rb +57 -0
  50. data/lib/3rb/lights/hemisphere_light.rb +26 -0
  51. data/lib/3rb/lights/light.rb +27 -0
  52. data/lib/3rb/lights/point_light.rb +68 -0
  53. data/lib/3rb/lights/rect_area_light.rb +35 -0
  54. data/lib/3rb/lights/spot_light.rb +88 -0
  55. data/lib/3rb/loaders/gltf_loader.rb +304 -0
  56. data/lib/3rb/loaders/loader.rb +94 -0
  57. data/lib/3rb/loaders/obj_loader.rb +186 -0
  58. data/lib/3rb/loaders/texture_loader.rb +55 -0
  59. data/lib/3rb/materials/basic_material.rb +70 -0
  60. data/lib/3rb/materials/lambert_material.rb +102 -0
  61. data/lib/3rb/materials/material.rb +114 -0
  62. data/lib/3rb/materials/phong_material.rb +106 -0
  63. data/lib/3rb/materials/shader_material.rb +104 -0
  64. data/lib/3rb/materials/standard_material.rb +106 -0
  65. data/lib/3rb/math/color.rb +246 -0
  66. data/lib/3rb/math/euler.rb +156 -0
  67. data/lib/3rb/math/math_utils.rb +132 -0
  68. data/lib/3rb/math/matrix3.rb +269 -0
  69. data/lib/3rb/math/matrix4.rb +501 -0
  70. data/lib/3rb/math/quaternion.rb +337 -0
  71. data/lib/3rb/math/vector2.rb +216 -0
  72. data/lib/3rb/math/vector3.rb +366 -0
  73. data/lib/3rb/math/vector4.rb +233 -0
  74. data/lib/3rb/native/gl.rb +382 -0
  75. data/lib/3rb/native/native.rb +55 -0
  76. data/lib/3rb/native/window.rb +111 -0
  77. data/lib/3rb/native.rb +9 -0
  78. data/lib/3rb/objects/line.rb +116 -0
  79. data/lib/3rb/objects/mesh.rb +40 -0
  80. data/lib/3rb/objects/points.rb +71 -0
  81. data/lib/3rb/renderers/opengl_renderer.rb +567 -0
  82. data/lib/3rb/renderers/renderer.rb +60 -0
  83. data/lib/3rb/renderers/shader_lib.rb +100 -0
  84. data/lib/3rb/textures/cube_texture.rb +26 -0
  85. data/lib/3rb/textures/data_texture.rb +35 -0
  86. data/lib/3rb/textures/render_target.rb +125 -0
  87. data/lib/3rb/textures/texture.rb +190 -0
  88. data/lib/3rb/version.rb +5 -0
  89. data/lib/3rb.rb +86 -0
  90. data/shaders/basic.frag +19 -0
  91. data/shaders/basic.vert +15 -0
  92. data/shaders/common/lights.glsl +53 -0
  93. data/shaders/common/uniforms.glsl +9 -0
  94. data/shaders/lambert.frag +37 -0
  95. data/shaders/lambert.vert +22 -0
  96. data/shaders/phong.frag +51 -0
  97. data/shaders/phong.vert +28 -0
  98. data/shaders/standard.frag +92 -0
  99. data/shaders/standard.vert +28 -0
  100. metadata +155 -0
@@ -0,0 +1,366 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sunrb
4
+ class Vector3
5
+ attr_accessor :x, :y, :z
6
+
7
+ def initialize(x = 0, y = 0, z = 0)
8
+ @x = x.to_f
9
+ @y = y.to_f
10
+ @z = z.to_f
11
+ end
12
+
13
+ def set(x, y, z)
14
+ @x = x.to_f
15
+ @y = y.to_f
16
+ @z = z.to_f
17
+ self
18
+ end
19
+
20
+ def set_scalar(scalar)
21
+ @x = @y = @z = scalar.to_f
22
+ self
23
+ end
24
+
25
+ def copy(v)
26
+ @x = v.x
27
+ @y = v.y
28
+ @z = v.z
29
+ self
30
+ end
31
+
32
+ def clone
33
+ Vector3.new(@x, @y, @z)
34
+ end
35
+
36
+ def +(other)
37
+ Vector3.new(@x + other.x, @y + other.y, @z + other.z)
38
+ end
39
+
40
+ def -(other)
41
+ Vector3.new(@x - other.x, @y - other.y, @z - other.z)
42
+ end
43
+
44
+ def *(scalar)
45
+ Vector3.new(@x * scalar, @y * scalar, @z * scalar)
46
+ end
47
+
48
+ def /(scalar)
49
+ Vector3.new(@x / scalar, @y / scalar, @z / scalar)
50
+ end
51
+
52
+ def -@
53
+ Vector3.new(-@x, -@y, -@z)
54
+ end
55
+
56
+ def add!(other)
57
+ @x += other.x
58
+ @y += other.y
59
+ @z += other.z
60
+ self
61
+ end
62
+
63
+ def sub!(other)
64
+ @x -= other.x
65
+ @y -= other.y
66
+ @z -= other.z
67
+ self
68
+ end
69
+
70
+ alias sub sub!
71
+
72
+ def add(other)
73
+ add!(other)
74
+ end
75
+
76
+ def multiply_scalar(scalar)
77
+ multiply_scalar!(scalar)
78
+ end
79
+
80
+ def multiply_scalar!(scalar)
81
+ @x *= scalar
82
+ @y *= scalar
83
+ @z *= scalar
84
+ self
85
+ end
86
+
87
+ def divide_scalar!(scalar)
88
+ @x /= scalar
89
+ @y /= scalar
90
+ @z /= scalar
91
+ self
92
+ end
93
+
94
+ def dot(other)
95
+ @x * other.x + @y * other.y + @z * other.z
96
+ end
97
+
98
+ def cross(other)
99
+ Vector3.new(
100
+ @y * other.z - @z * other.y,
101
+ @z * other.x - @x * other.z,
102
+ @x * other.y - @y * other.x
103
+ )
104
+ end
105
+
106
+ def cross!(other)
107
+ x = @y * other.z - @z * other.y
108
+ y = @z * other.x - @x * other.z
109
+ z = @x * other.y - @y * other.x
110
+ @x = x
111
+ @y = y
112
+ @z = z
113
+ self
114
+ end
115
+
116
+ def length_sq
117
+ @x * @x + @y * @y + @z * @z
118
+ end
119
+
120
+ def length
121
+ Math.sqrt(length_sq)
122
+ end
123
+
124
+ def normalize
125
+ clone.normalize!
126
+ end
127
+
128
+ def normalize!
129
+ len = length
130
+ return self if len.zero?
131
+
132
+ divide_scalar!(len)
133
+ end
134
+
135
+ def distance_to(other)
136
+ (self - other).length
137
+ end
138
+
139
+ def distance_to_sq(other)
140
+ (self - other).length_sq
141
+ end
142
+
143
+ def lerp(other, alpha)
144
+ Vector3.new(
145
+ @x + (other.x - @x) * alpha,
146
+ @y + (other.y - @y) * alpha,
147
+ @z + (other.z - @z) * alpha
148
+ )
149
+ end
150
+
151
+ def lerp!(other, alpha)
152
+ @x += (other.x - @x) * alpha
153
+ @y += (other.y - @y) * alpha
154
+ @z += (other.z - @z) * alpha
155
+ self
156
+ end
157
+
158
+ def negate!
159
+ @x = -@x
160
+ @y = -@y
161
+ @z = -@z
162
+ self
163
+ end
164
+
165
+ def min(other)
166
+ Vector3.new(
167
+ [@x, other.x].min,
168
+ [@y, other.y].min,
169
+ [@z, other.z].min
170
+ )
171
+ end
172
+
173
+ def max(other)
174
+ Vector3.new(
175
+ [@x, other.x].max,
176
+ [@y, other.y].max,
177
+ [@z, other.z].max
178
+ )
179
+ end
180
+
181
+ def clamp(min_vec, max_vec)
182
+ Vector3.new(
183
+ [[@x, min_vec.x].max, max_vec.x].min,
184
+ [[@y, min_vec.y].max, max_vec.y].min,
185
+ [[@z, min_vec.z].max, max_vec.z].min
186
+ )
187
+ end
188
+
189
+ def floor
190
+ Vector3.new(@x.floor, @y.floor, @z.floor)
191
+ end
192
+
193
+ def ceil
194
+ Vector3.new(@x.ceil, @y.ceil, @z.ceil)
195
+ end
196
+
197
+ def round
198
+ Vector3.new(@x.round, @y.round, @z.round)
199
+ end
200
+
201
+ def angle_to(other)
202
+ denominator = Math.sqrt(length_sq * other.length_sq)
203
+ return Math::PI / 2 if denominator.zero?
204
+
205
+ theta = dot(other) / denominator
206
+ Math.acos([[-1, theta].max, 1].min)
207
+ end
208
+
209
+ def project_on_vector(other)
210
+ denominator = other.length_sq
211
+ return Vector3.new if denominator.zero?
212
+
213
+ scalar = other.dot(self) / denominator
214
+ other * scalar
215
+ end
216
+
217
+ def reflect(normal)
218
+ self - normal * 2 * dot(normal)
219
+ end
220
+
221
+ def apply_matrix3(m)
222
+ x = @x
223
+ y = @y
224
+ z = @z
225
+ e = m.elements
226
+
227
+ Vector3.new(
228
+ e[0] * x + e[3] * y + e[6] * z,
229
+ e[1] * x + e[4] * y + e[7] * z,
230
+ e[2] * x + e[5] * y + e[8] * z
231
+ )
232
+ end
233
+
234
+ def apply_matrix4(m)
235
+ x = @x
236
+ y = @y
237
+ z = @z
238
+ e = m.elements
239
+
240
+ w = 1.0 / (e[3] * x + e[7] * y + e[11] * z + e[15])
241
+
242
+ Vector3.new(
243
+ (e[0] * x + e[4] * y + e[8] * z + e[12]) * w,
244
+ (e[1] * x + e[5] * y + e[9] * z + e[13]) * w,
245
+ (e[2] * x + e[6] * y + e[10] * z + e[14]) * w
246
+ )
247
+ end
248
+
249
+ def set_from_spherical(s)
250
+ sin_phi_radius = Math.sin(s.phi) * s.radius
251
+ @x = sin_phi_radius * Math.sin(s.theta)
252
+ @y = Math.cos(s.phi) * s.radius
253
+ @z = sin_phi_radius * Math.cos(s.theta)
254
+ self
255
+ end
256
+
257
+ def set_from_matrix_column(matrix, index)
258
+ from_array(matrix.elements, index * 4)
259
+ end
260
+
261
+ def from_array(array, offset = 0)
262
+ @x = array[offset].to_f
263
+ @y = array[offset + 1].to_f
264
+ @z = array[offset + 2].to_f
265
+ self
266
+ end
267
+
268
+ def cross_vectors(a, b)
269
+ @x = a.y * b.z - a.z * b.y
270
+ @y = a.z * b.x - a.x * b.z
271
+ @z = a.x * b.y - a.y * b.x
272
+ self
273
+ end
274
+
275
+ def set_from_matrix_position(m)
276
+ e = m.elements
277
+ @x = e[12]
278
+ @y = e[13]
279
+ @z = e[14]
280
+ self
281
+ end
282
+
283
+ def apply_quaternion(q)
284
+ x = @x
285
+ y = @y
286
+ z = @z
287
+ qx = q.x
288
+ qy = q.y
289
+ qz = q.z
290
+ qw = q.w
291
+
292
+ ix = qw * x + qy * z - qz * y
293
+ iy = qw * y + qz * x - qx * z
294
+ iz = qw * z + qx * y - qy * x
295
+ iw = -qx * x - qy * y - qz * z
296
+
297
+ Vector3.new(
298
+ ix * qw + iw * -qx + iy * -qz - iz * -qy,
299
+ iy * qw + iw * -qy + iz * -qx - ix * -qz,
300
+ iz * qw + iw * -qz + ix * -qy - iy * -qx
301
+ )
302
+ end
303
+
304
+ def ==(other)
305
+ return false unless other.is_a?(Vector3)
306
+
307
+ (@x - other.x).abs < Float::EPSILON &&
308
+ (@y - other.y).abs < Float::EPSILON &&
309
+ (@z - other.z).abs < Float::EPSILON
310
+ end
311
+
312
+ def equals?(other, tolerance = Float::EPSILON)
313
+ return false unless other.is_a?(Vector3)
314
+
315
+ (@x - other.x).abs <= tolerance &&
316
+ (@y - other.y).abs <= tolerance &&
317
+ (@z - other.z).abs <= tolerance
318
+ end
319
+
320
+ def to_a
321
+ [@x, @y, @z]
322
+ end
323
+
324
+ def to_h
325
+ { x: @x, y: @y, z: @z }
326
+ end
327
+
328
+ def inspect
329
+ "#<Sunrb::Vector3 x=#{@x} y=#{@y} z=#{@z}>"
330
+ end
331
+
332
+ class << self
333
+ def zero
334
+ new(0, 0, 0)
335
+ end
336
+
337
+ def one
338
+ new(1, 1, 1)
339
+ end
340
+
341
+ def up
342
+ new(0, 1, 0)
343
+ end
344
+
345
+ def down
346
+ new(0, -1, 0)
347
+ end
348
+
349
+ def forward
350
+ new(0, 0, -1)
351
+ end
352
+
353
+ def back
354
+ new(0, 0, 1)
355
+ end
356
+
357
+ def left
358
+ new(-1, 0, 0)
359
+ end
360
+
361
+ def right
362
+ new(1, 0, 0)
363
+ end
364
+ end
365
+ end
366
+ end
@@ -0,0 +1,233 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sunrb
4
+ class Vector4
5
+ attr_accessor :x, :y, :z, :w
6
+
7
+ def initialize(x = 0, y = 0, z = 0, w = 1)
8
+ @x = x.to_f
9
+ @y = y.to_f
10
+ @z = z.to_f
11
+ @w = w.to_f
12
+ end
13
+
14
+ def set(x, y, z, w)
15
+ @x = x.to_f
16
+ @y = y.to_f
17
+ @z = z.to_f
18
+ @w = w.to_f
19
+ self
20
+ end
21
+
22
+ def set_scalar(scalar)
23
+ @x = @y = @z = @w = scalar.to_f
24
+ self
25
+ end
26
+
27
+ def copy(v)
28
+ @x = v.x
29
+ @y = v.y
30
+ @z = v.z
31
+ @w = v.respond_to?(:w) ? v.w : 1.0
32
+ self
33
+ end
34
+
35
+ def clone
36
+ Vector4.new(@x, @y, @z, @w)
37
+ end
38
+
39
+ def +(other)
40
+ Vector4.new(@x + other.x, @y + other.y, @z + other.z, @w + other.w)
41
+ end
42
+
43
+ def -(other)
44
+ Vector4.new(@x - other.x, @y - other.y, @z - other.z, @w - other.w)
45
+ end
46
+
47
+ def *(scalar)
48
+ Vector4.new(@x * scalar, @y * scalar, @z * scalar, @w * scalar)
49
+ end
50
+
51
+ def /(scalar)
52
+ Vector4.new(@x / scalar, @y / scalar, @z / scalar, @w / scalar)
53
+ end
54
+
55
+ def -@
56
+ Vector4.new(-@x, -@y, -@z, -@w)
57
+ end
58
+
59
+ def add!(other)
60
+ @x += other.x
61
+ @y += other.y
62
+ @z += other.z
63
+ @w += other.w
64
+ self
65
+ end
66
+
67
+ def sub!(other)
68
+ @x -= other.x
69
+ @y -= other.y
70
+ @z -= other.z
71
+ @w -= other.w
72
+ self
73
+ end
74
+
75
+ def multiply_scalar!(scalar)
76
+ @x *= scalar
77
+ @y *= scalar
78
+ @z *= scalar
79
+ @w *= scalar
80
+ self
81
+ end
82
+
83
+ def divide_scalar!(scalar)
84
+ @x /= scalar
85
+ @y /= scalar
86
+ @z /= scalar
87
+ @w /= scalar
88
+ self
89
+ end
90
+
91
+ def dot(other)
92
+ @x * other.x + @y * other.y + @z * other.z + @w * other.w
93
+ end
94
+
95
+ def length_sq
96
+ @x * @x + @y * @y + @z * @z + @w * @w
97
+ end
98
+
99
+ def length
100
+ Math.sqrt(length_sq)
101
+ end
102
+
103
+ def normalize
104
+ clone.normalize!
105
+ end
106
+
107
+ def normalize!
108
+ len = length
109
+ return self if len.zero?
110
+
111
+ divide_scalar!(len)
112
+ end
113
+
114
+ def lerp(other, alpha)
115
+ Vector4.new(
116
+ @x + (other.x - @x) * alpha,
117
+ @y + (other.y - @y) * alpha,
118
+ @z + (other.z - @z) * alpha,
119
+ @w + (other.w - @w) * alpha
120
+ )
121
+ end
122
+
123
+ def lerp!(other, alpha)
124
+ @x += (other.x - @x) * alpha
125
+ @y += (other.y - @y) * alpha
126
+ @z += (other.z - @z) * alpha
127
+ @w += (other.w - @w) * alpha
128
+ self
129
+ end
130
+
131
+ def negate!
132
+ @x = -@x
133
+ @y = -@y
134
+ @z = -@z
135
+ @w = -@w
136
+ self
137
+ end
138
+
139
+ def min(other)
140
+ Vector4.new(
141
+ [@x, other.x].min,
142
+ [@y, other.y].min,
143
+ [@z, other.z].min,
144
+ [@w, other.w].min
145
+ )
146
+ end
147
+
148
+ def max(other)
149
+ Vector4.new(
150
+ [@x, other.x].max,
151
+ [@y, other.y].max,
152
+ [@z, other.z].max,
153
+ [@w, other.w].max
154
+ )
155
+ end
156
+
157
+ def clamp(min_vec, max_vec)
158
+ Vector4.new(
159
+ [[@x, min_vec.x].max, max_vec.x].min,
160
+ [[@y, min_vec.y].max, max_vec.y].min,
161
+ [[@z, min_vec.z].max, max_vec.z].min,
162
+ [[@w, min_vec.w].max, max_vec.w].min
163
+ )
164
+ end
165
+
166
+ def floor
167
+ Vector4.new(@x.floor, @y.floor, @z.floor, @w.floor)
168
+ end
169
+
170
+ def ceil
171
+ Vector4.new(@x.ceil, @y.ceil, @z.ceil, @w.ceil)
172
+ end
173
+
174
+ def round
175
+ Vector4.new(@x.round, @y.round, @z.round, @w.round)
176
+ end
177
+
178
+ def apply_matrix4(m)
179
+ x = @x
180
+ y = @y
181
+ z = @z
182
+ w = @w
183
+ e = m.elements
184
+
185
+ Vector4.new(
186
+ e[0] * x + e[4] * y + e[8] * z + e[12] * w,
187
+ e[1] * x + e[5] * y + e[9] * z + e[13] * w,
188
+ e[2] * x + e[6] * y + e[10] * z + e[14] * w,
189
+ e[3] * x + e[7] * y + e[11] * z + e[15] * w
190
+ )
191
+ end
192
+
193
+ def ==(other)
194
+ return false unless other.is_a?(Vector4)
195
+
196
+ (@x - other.x).abs < Float::EPSILON &&
197
+ (@y - other.y).abs < Float::EPSILON &&
198
+ (@z - other.z).abs < Float::EPSILON &&
199
+ (@w - other.w).abs < Float::EPSILON
200
+ end
201
+
202
+ def equals?(other, tolerance = Float::EPSILON)
203
+ return false unless other.is_a?(Vector4)
204
+
205
+ (@x - other.x).abs <= tolerance &&
206
+ (@y - other.y).abs <= tolerance &&
207
+ (@z - other.z).abs <= tolerance &&
208
+ (@w - other.w).abs <= tolerance
209
+ end
210
+
211
+ def to_a
212
+ [@x, @y, @z, @w]
213
+ end
214
+
215
+ def to_h
216
+ { x: @x, y: @y, z: @z, w: @w }
217
+ end
218
+
219
+ def inspect
220
+ "#<Sunrb::Vector4 x=#{@x} y=#{@y} z=#{@z} w=#{@w}>"
221
+ end
222
+
223
+ class << self
224
+ def zero
225
+ new(0, 0, 0, 0)
226
+ end
227
+
228
+ def one
229
+ new(1, 1, 1, 1)
230
+ end
231
+ end
232
+ end
233
+ end