mittsu 0.2.3 → 0.3.3

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build-workflow.yml +95 -0
  3. data/.gitignore +1 -0
  4. data/Gemfile +3 -2
  5. data/README.md +3 -7
  6. data/Rakefile +1 -0
  7. data/install-glfw.ps1 +13 -0
  8. data/lib/mittsu.rb +1 -16
  9. data/lib/mittsu/cameras/camera.rb +0 -2
  10. data/lib/mittsu/cameras/cube_camera.rb +0 -2
  11. data/lib/mittsu/cameras/orthographic_camera.rb +2 -4
  12. data/lib/mittsu/cameras/perspective_camera.rb +4 -5
  13. data/lib/mittsu/core/buffer_geometry.rb +3 -3
  14. data/lib/mittsu/core/geometry.rb +10 -9
  15. data/lib/mittsu/core/object_3d.rb +9 -7
  16. data/lib/mittsu/core/raycaster.rb +0 -2
  17. data/lib/mittsu/extras/geometries.rb +13 -0
  18. data/lib/mittsu/extras/geometries/circle_geometry.rb +48 -0
  19. data/lib/mittsu/extras/geometries/cylinder_geometry.rb +145 -0
  20. data/lib/mittsu/extras/geometries/dodecahedron_geometry.rb +56 -0
  21. data/lib/mittsu/extras/geometries/icosahedron_geometry.rb +33 -0
  22. data/lib/mittsu/extras/geometries/lathe_geometry.rb +78 -0
  23. data/lib/mittsu/extras/geometries/octahedron_geometry.rb +26 -0
  24. data/lib/mittsu/extras/geometries/parametric_buffer_geometry.rb +92 -0
  25. data/lib/mittsu/extras/geometries/parametric_geometry.rb +93 -0
  26. data/lib/mittsu/extras/geometries/plane_buffer_geometry.rb +81 -0
  27. data/lib/mittsu/extras/geometries/plane_geometry.rb +22 -0
  28. data/lib/mittsu/extras/geometries/polyhedron_geometry.rb +168 -0
  29. data/lib/mittsu/extras/geometries/ring_geometry.rb +80 -0
  30. data/lib/mittsu/extras/geometries/sphere_geometry.rb +4 -4
  31. data/lib/mittsu/extras/geometries/tetrahedron_geometry.rb +26 -0
  32. data/lib/mittsu/extras/geometries/torus_geometry.rb +63 -0
  33. data/lib/mittsu/extras/geometries/torus_knot_buffer_geometry.rb +120 -0
  34. data/lib/mittsu/extras/geometries/torus_knot_geometry.rb +25 -0
  35. data/lib/mittsu/extras/helpers/camera_helper.rb +38 -38
  36. data/lib/mittsu/extras/image_utils.rb +1 -1
  37. data/lib/mittsu/lights/directional_light.rb +9 -5
  38. data/lib/mittsu/lights/spot_light.rb +1 -1
  39. data/lib/mittsu/loaders/loader.rb +2 -2
  40. data/lib/mittsu/loaders/obj_loader.rb +4 -0
  41. data/lib/mittsu/materials/material.rb +6 -3
  42. data/lib/mittsu/math.rb +0 -5
  43. data/lib/mittsu/math/box2.rb +0 -2
  44. data/lib/mittsu/math/box3.rb +0 -2
  45. data/lib/mittsu/math/color.rb +3 -4
  46. data/lib/mittsu/math/euler.rb +25 -26
  47. data/lib/mittsu/math/frustum.rb +0 -2
  48. data/lib/mittsu/math/line3.rb +0 -2
  49. data/lib/mittsu/math/matrix3.rb +0 -2
  50. data/lib/mittsu/math/matrix4.rb +10 -12
  51. data/lib/mittsu/math/plane.rb +0 -2
  52. data/lib/mittsu/math/quaternion.rb +18 -20
  53. data/lib/mittsu/math/ray.rb +1 -3
  54. data/lib/mittsu/math/sphere.rb +1 -3
  55. data/lib/mittsu/math/spline.rb +0 -2
  56. data/lib/mittsu/math/triangle.rb +1 -3
  57. data/lib/mittsu/math/vector.rb +4 -4
  58. data/lib/mittsu/math/vector2.rb +0 -1
  59. data/lib/mittsu/math/vector3.rb +0 -1
  60. data/lib/mittsu/math/vector4.rb +8 -9
  61. data/lib/mittsu/objects/line.rb +0 -1
  62. data/lib/mittsu/renderers/glfw_lib.rb +1 -1
  63. data/lib/mittsu/renderers/glfw_window.rb +1 -1
  64. data/lib/mittsu/renderers/opengl/core/object_3d.rb +1 -1
  65. data/lib/mittsu/renderers/opengl/lights/spot_light.rb +1 -1
  66. data/lib/mittsu/renderers/opengl/opengl_geometry_group.rb +1 -0
  67. data/lib/mittsu/renderers/opengl/opengl_program.rb +1 -2
  68. data/lib/mittsu/renderers/opengl/textures/texture.rb +1 -1
  69. data/lib/mittsu/renderers/opengl_renderer.rb +5 -10
  70. data/lib/mittsu/scenes/scene.rb +0 -2
  71. data/lib/mittsu/textures/texture.rb +4 -2
  72. data/lib/mittsu/utils.rb +15 -0
  73. data/lib/mittsu/version.rb +1 -1
  74. data/mittsu.gemspec +10 -9
  75. metadata +75 -47
  76. data/.circleci/config.yml +0 -44
  77. data/.travis.yml +0 -20
  78. data/appveyor.yml +0 -23
  79. data/install_glfw.ps1 +0 -11
@@ -0,0 +1,81 @@
1
+ module Mittsu
2
+ class PlaneBufferGeometry < BufferGeometry
3
+ def initialize(width, height, width_segments = 1, height_segments = 1)
4
+ super()
5
+
6
+ @type = 'PlaneBufferGeometry'
7
+
8
+ @parameters = {
9
+ width: width,
10
+ height: height,
11
+ width_segments: width_segments,
12
+ height_segments: height_segments
13
+ }
14
+
15
+ width_half = width / 2.0
16
+ height_half = height / 2.0
17
+
18
+ grid_x = width_segments || 1
19
+ grid_y = height_segments || 1
20
+
21
+ grid_x1 = grid_x + 1
22
+ grid_y1 = grid_y + 1
23
+
24
+ segment_width = width.to_f / grid_x.to_f
25
+ segment_height = height.to_f / grid_y.to_f
26
+
27
+ vertices = Array.new(grid_x1 * grid_y1 * 3) # Float32Array
28
+ normals = Array.new(grid_x1 * grid_y1 * 3) #Float32Array
29
+ uvs = Array.new(grid_x1 * grid_y1 * 2) # Float32Array
30
+
31
+ offset = 0
32
+ offset2 = 0
33
+
34
+ for iy in 0...grid_y1 do
35
+ y = iy.to_f * segment_height - height_half
36
+ for ix in 0...grid_x1 do
37
+ x = ix.to_f * segment_width - width_half
38
+
39
+ vertices[offset] = x
40
+ vertices[offset + 1] = -y
41
+
42
+ normals[offset + 2] = 1.0
43
+
44
+ uvs[offset2] = ix.to_f / grid_x.to_f
45
+ uvs[offset2 + 1] = 1.0 - (iy.to_f / grid_y.to_f)
46
+
47
+ offset += 3
48
+ offset2 += 2
49
+ end
50
+ end
51
+
52
+ offset = 0
53
+
54
+ indices = Array.new(grid_x * grid_y * 6) # ( ( vertices.length / 3 ) > 65535 ? Uint32Array : Uint16Array )
55
+
56
+ for iy in 0...grid_y do
57
+ for ix in 0...grid_x do
58
+ a = ix + grid_x1 * iy
59
+ b = ix + grid_x1 * (iy + 1)
60
+ c = (ix + 1) + grid_x1 * (iy + 1)
61
+ d = (ix + 1) + grid_x1 * iy
62
+
63
+ indices[offset ] = a
64
+ indices[offset + 1] = b
65
+ indices[offset + 2] = d
66
+
67
+ indices[offset + 3] = b
68
+ indices[offset + 4] = c
69
+ indices[offset + 5] = d
70
+
71
+ offset += 6
72
+ end
73
+ end
74
+
75
+ self[:index] = BufferAttribute.new(indices, 1)
76
+ self[:position] = BufferAttribute.new(vertices, 3)
77
+ self[:normal] = BufferAttribute.new(normals, 3)
78
+ self[:uv] = BufferAttribute.new(uvs, 2)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,22 @@
1
+ require 'mittsu/extras/geometries/plane_buffer_geometry'
2
+
3
+ module Mittsu
4
+ class PlaneGeometry < Geometry
5
+ def initialize(width, height, width_segments = 1, height_segments = 1)
6
+ puts 'Mittsu::PlaneGeometry: Consider using Mittsu::PlaneBufferGeometry for lower memory footprint.'
7
+
8
+ super()
9
+
10
+ @type = 'PlaneGeometry'
11
+
12
+ @parameters = {
13
+ width: width,
14
+ height: height,
15
+ width_segments: width_segments,
16
+ height_segments: height_segments
17
+ }
18
+
19
+ from_buffer_geometry(PlaneBufferGeometry.new(width, height, width_segments, height_segments))
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,168 @@
1
+ require 'mittsu/core'
2
+ require 'mittsu/math'
3
+
4
+ module Mittsu
5
+ class PolyhedronGeometry < Geometry
6
+ def initialize(vertices, indices, radius = 1.0, detail = 0)
7
+ super()
8
+
9
+ @type = 'PolyhedronGeometry'
10
+
11
+ @parameters = {
12
+ vertices: vertices,
13
+ indices: indices,
14
+ radius: radius,
15
+ detail: detail
16
+ }
17
+
18
+ for i in (0...vertices.length).step(3) do
19
+ prepare(Vector3.new(vertices[i], vertices[i + 1], vertices[i + 2]))
20
+ end
21
+
22
+ faces = []
23
+
24
+ i = 0
25
+ j = 0
26
+ while i < indices.length do
27
+ v1 = @vertices[indices[i]]
28
+ v2 = @vertices[indices[i + 1]]
29
+ v3 = @vertices[indices[i + 2]]
30
+ binding.irb if v1.nil? || v2.nil? || v3.nil?
31
+
32
+ faces[j] = Face3.new(v1.index, v2.index, v3.index, [v1.clone, v2.clone, v3.clone])
33
+
34
+ i += 3
35
+ j += 1
36
+ end
37
+
38
+ @centroid = Vector3.new
39
+
40
+ for i in 0...faces.length do
41
+ subdivide(faces[i], detail)
42
+ end
43
+
44
+ # Handle case when face straddles the seam
45
+
46
+ @face_vertex_uvs[0].each do |uv0, uv1, uv2|
47
+ x0 = uv0.x
48
+ x1 = uv1.x
49
+ x2 = uv2.x
50
+
51
+ max = [x0, x1, x2].max
52
+ min = [x0, x1, x2].min
53
+
54
+ if max > 0.9 && min < 0.1 # 0.9 is somewhat arbitrary
55
+ uv0.x += 1.0 if x0 < 0.2
56
+ uv1.x += 1.0 if x1 < 0.2
57
+ uv2.x += 1.0 if x2 < 0.2
58
+ end
59
+ end
60
+
61
+ # Apply radius
62
+
63
+ @vertices.each do |v|
64
+ v.multiply_scalar(radius)
65
+ end
66
+
67
+ merge_vertices
68
+
69
+ compute_face_normals
70
+ @bounding_sphere = Sphere.new(Vector3.new, radius)
71
+ end
72
+
73
+ private
74
+
75
+ # Project vector onto sphere's surface
76
+ def prepare(vector)
77
+ vertex = vector.normalize.clone
78
+ vertex.index = @vertices.push(vertex).length - 1
79
+
80
+ # Texture coords are equivalent to map coords, calculate angle and convert to fraction of a circle.
81
+ u = azimuth(vector) / 2.0 / ::Math::PI + 0.5
82
+ v = inclination(vector) / ::Math::PI + 0.5
83
+ vertex.uv = Vector2.new(u, 1.0 - v)
84
+
85
+ vertex
86
+ end
87
+
88
+ # Approximate a curved face with recursively sub-divided triangles.
89
+ def make(v1, v2, v3)
90
+ face = Face3.new(v1.index, v2.index, v3.index, [v1.clone, v2.clone, v3.clone])
91
+ @faces << face
92
+
93
+ @centroid.copy(v1).add(v2).add(v3).divide_scalar(3)
94
+
95
+ azi = azimuth(@centroid)
96
+
97
+ @face_vertex_uvs[0] << [
98
+ correct_uv(v1.uv, v1, azi),
99
+ correct_uv(v2.uv, v2, azi),
100
+ correct_uv(v3.uv, v3, azi)
101
+ ]
102
+ end
103
+
104
+ # Analytically subdivide a face to the required detail level.
105
+ def subdivide(face, detail)
106
+ cols = 2.0 ** detail
107
+ a = prepare(@vertices[face.a])
108
+ b = prepare(@vertices[face.b])
109
+ c = prepare(@vertices[face.c])
110
+ v = []
111
+
112
+ # Construct all of the vertices for this subdivision.
113
+ for i in 0..cols do
114
+ v[i] = []
115
+
116
+ aj = prepare(a.clone.lerp(c, i.to_f / cols.to_f))
117
+ bj = prepare(b.clone.lerp(c, i.to_f / cols.to_f))
118
+ rows = cols - i
119
+
120
+ for j in 0..rows do
121
+ v[i][j] = if j.zero? && i == cols
122
+ aj
123
+ else
124
+ prepare(aj.clone.lerp(bj, j.to_f / rows.to_f))
125
+ end
126
+ end
127
+ end
128
+
129
+ # Construct all of the faces
130
+ for i in 0...cols do
131
+ for j in (0...(2 * (cols - i) - 1)) do
132
+ k = j/2
133
+
134
+ if j.even?
135
+ make(
136
+ v[i][k + 1],
137
+ v[i + 1][k],
138
+ v[i][k]
139
+ )
140
+ else
141
+ make(
142
+ v[i][k + 1],
143
+ v[i + 1][k + 1],
144
+ v[i + 1][k]
145
+ )
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ # Angle around the Y axis, counter-clockwise when looking from above.
152
+ def azimuth(vector)
153
+ ::Math.atan2(vector.z, -vector.x)
154
+ end
155
+
156
+ # Angle above the XZ plane.
157
+ def inclination(vector)
158
+ ::Math.atan2(-vector.y, ::Math.sqrt(vector.x * vector.x + vector.z * vector.z))
159
+ end
160
+
161
+ # Texture fixing helper. Spheres have some odd behaviours.
162
+ def correct_uv(uv, vector, azimuth)
163
+ return Vector2.new(uv.x - 1.0, uv.y) if azimuth < 0
164
+ return Vector2.new(azimuth / 2.0 / ::Math::PI + 0.5, uv.y) if vector.x.zero? && vector.z.zero?
165
+ uv.clone
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,80 @@
1
+ require 'mittsu/core'
2
+ require 'mittsu/math'
3
+
4
+ module Mittsu
5
+ class RingGeometry < Geometry
6
+ def initialize(inner_radius = 0.0, outer_radius = 50.0, theta_segments = 8, phi_segments = 8, theta_start = 0.0, theta_length = (::Math::PI * 2.0))
7
+ super()
8
+
9
+ @type = 'RingGeometry'
10
+
11
+ @parameters = {
12
+ inner_radius: inner_radius,
13
+ outer_radius: outer_radius,
14
+ theta_segments: theta_segments,
15
+ phi_segments: phi_segments,
16
+ theta_start: theta_start,
17
+ theta_length: theta_length
18
+ }
19
+
20
+ theta_segments = [3, theta_segments].max
21
+ phi_segments = [1, phi_segments].max
22
+
23
+ uvs = []
24
+ radius = inner_radius
25
+ radius_step = ((outer_radius - inner_radius) / phi_segments.to_f)
26
+
27
+ for i in 0..phi_segments do # concentric circles inside ring
28
+ for o in 0..theta_segments do # number of segments per circle
29
+ vertex = Vector3.new
30
+ segment = theta_start + o.to_f / theta_segments.to_f * theta_length
31
+ vertex.x = radius * ::Math.cos(segment)
32
+ vertex.y = radius * ::Math.sin(segment)
33
+
34
+ @vertices << vertex
35
+ uvs << Vector2.new((vertex.x / outer_radius + 1.0) / 2.0, (vertex.y / outer_radius + 1.0) / 2.0)
36
+ end
37
+
38
+ radius += radius_step
39
+ end
40
+
41
+ n = Vector3.new(0.0, 0.0, 1.0)
42
+
43
+ for i in 0...phi_segments do # concentric circles inside ring
44
+ theta_segment = i * (theta_segments + 1)
45
+
46
+ for o in 0...theta_segments do # number of segments per circle
47
+ segment = o + theta_segment
48
+
49
+ v1 = segment
50
+ v2 = segment + theta_segments + 1
51
+ v3 = segment + theta_segments + 2
52
+
53
+ @faces << Face3.new(v1, v2, v3, [n.clone, n.clone, n.clone])
54
+ @face_vertex_uvs[0] << [uvs[v1].clone, uvs[v2].clone, uvs[v3].clone]
55
+
56
+ v1 = segment
57
+ v2 = segment + theta_segments + 2
58
+ v3 = segment + 1
59
+
60
+ @faces << Face3.new(v1, v2, v3, [n.clone, n.clone, n.clone])
61
+ @face_vertex_uvs[0] << [uvs[v1].clone, uvs[v2].clone, uvs[v3].clone]
62
+ end
63
+ end
64
+
65
+ compute_face_normals
66
+ @bounding_sphere = Sphere.new(Vector3.new, radius)
67
+ end
68
+
69
+ def clone
70
+ RingGeometry.new(
71
+ @parameters[:inner_radius],
72
+ @parameters[:outer_radius],
73
+ @parameters[:theta_segments],
74
+ @parameters[:phi_segments],
75
+ @parameters[:theta_start],
76
+ @parameters[:theta_length]
77
+ )
78
+ end
79
+ end
80
+ end
@@ -3,7 +3,7 @@ require 'mittsu/math'
3
3
 
4
4
  module Mittsu
5
5
  class SphereGeometry < Geometry
6
- def initialize(radius = 50.0, width_segments = 8, height_segments = 6, phi_start = 0.0, phi_length = (Math::PI * 2.0), theta_start = 0.0, theta_length = Math::PI)
6
+ def initialize(radius = 50.0, width_segments = 8, height_segments = 6, phi_start = 0.0, phi_length = (::Math::PI * 2.0), theta_start = 0.0, theta_length = ::Math::PI)
7
7
  super()
8
8
 
9
9
  @type = 'SphereGeometry'
@@ -33,9 +33,9 @@ module Mittsu
33
33
  v = y / height_segments.to_f
34
34
 
35
35
  vertex = Vector3.new
36
- vertex.x = -radius * Math.cos(phi_start + u * phi_length) * Math.sin(theta_start + v * theta_length)
37
- vertex.y = radius * Math.cos(theta_start + v * theta_length)
38
- vertex.z = radius * Math.sin(phi_start + u * phi_length) * Math.sin(theta_start + v * theta_length)
36
+ vertex.x = -radius * ::Math.cos(phi_start + u * phi_length) * ::Math.sin(theta_start + v * theta_length)
37
+ vertex.y = radius * ::Math.cos(theta_start + v * theta_length)
38
+ vertex.z = radius * ::Math.sin(phi_start + u * phi_length) * ::Math.sin(theta_start + v * theta_length)
39
39
 
40
40
  @vertices << vertex
41
41
 
@@ -0,0 +1,26 @@
1
+ require 'mittsu/core'
2
+ require 'mittsu/math'
3
+ require 'mittsu/extras/geometries/polyhedron_geometry'
4
+
5
+ module Mittsu
6
+ class TetrahedronGeometry < PolyhedronGeometry
7
+ def initialize(radius = 1.0, detail = 0)
8
+ vertices = [
9
+ 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1
10
+ ]
11
+
12
+ indices = [
13
+ 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1
14
+ ]
15
+
16
+ super(vertices, indices, radius, detail)
17
+
18
+ @type = 'TetrahedronGeometry'
19
+
20
+ @parameters = {
21
+ radius: radius,
22
+ detail: detail
23
+ }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,63 @@
1
+ require 'mittsu/core'
2
+ require 'mittsu/math'
3
+
4
+ module Mittsu
5
+ class TorusGeometry < Geometry
6
+ def initialize(radius = 100.0, tube = 40.0, radial_segments = 8, tubular_segments = 6, arc = (::Math::PI * 2.0))
7
+ super()
8
+
9
+ @type = 'TorusGeometry'
10
+
11
+ @parameters = {
12
+ radius: radius,
13
+ tube: tube,
14
+ radial_segments: radial_segments,
15
+ tubular_segments: tubular_segments,
16
+ arc: arc
17
+ }
18
+
19
+ center = Vector3.new
20
+ uvs = []
21
+ normals = []
22
+
23
+ for j in 0..radial_segments do
24
+ for i in 0..tubular_segments do
25
+ u = i.to_f / tubular_segments * arc
26
+ v = j.to_f / radial_segments * ::Math::PI * 2.0
27
+
28
+ center.x = radius * ::Math.cos(u)
29
+ center.y = radius * ::Math.sin(u)
30
+
31
+ vertex = Vector3.new
32
+ vertex.x = (radius + tube * ::Math.cos(v)) * ::Math.cos(u)
33
+ vertex.y = (radius + tube * ::Math.cos(v)) * ::Math.sin(u)
34
+ vertex.z = tube * ::Math.sin(v)
35
+
36
+ @vertices << vertex
37
+
38
+ uvs << Vector2.new(i.to_f / tubular_segments, j.to_f / radial_segments)
39
+ normals << vertex.clone.sub(center).normalize
40
+ end
41
+ end
42
+
43
+ for j in 1..radial_segments do
44
+ for i in 1..tubular_segments do
45
+ a = (tubular_segments + 1) * j + i - 1
46
+ b = (tubular_segments + 1) * (j - 1) + i - 1
47
+ c = (tubular_segments + 1) * (j - 1) + i
48
+ d = (tubular_segments + 1) * j + i
49
+
50
+ face = Face3.new(a, b, d, [normals[a].clone, normals[b].clone, normals[d].clone])
51
+ @faces << face
52
+ @face_vertex_uvs[0] << [uvs[a].clone, uvs[b].clone, uvs[d].clone]
53
+
54
+ face = Face3.new(b, c, d, [normals[b].clone, normals[c].clone, normals[d].clone])
55
+ @faces << face
56
+ @face_vertex_uvs[0] << [uvs[b].clone, uvs[c].clone, uvs[d].clone]
57
+ end
58
+ end
59
+
60
+ compute_face_normals
61
+ end
62
+ end
63
+ end