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,145 @@
1
+ require 'mittsu/core'
2
+ require 'mittsu/math'
3
+
4
+ module Mittsu
5
+ class CylinderGeometry < Geometry
6
+ def initialize(radius_top = 20.0, radius_bottom = 20.0, height = 100.0, radial_segments = 8, height_segments = 1, open_ended = false, theta_start = 0.0, theta_length = (::Math::PI * 2.0))
7
+ super()
8
+
9
+ @type = 'CylinderGeometry'
10
+
11
+ @parameters = {
12
+ radius_top: radius_top,
13
+ radius_bottom: radius_bottom,
14
+ height: height,
15
+ radial_segments: radial_segments,
16
+ height_segments: height_segments,
17
+ open_ended: open_ended,
18
+ theta_start: theta_start,
19
+ theta_length: theta_length
20
+ }
21
+
22
+ height_half = height / 2.0
23
+
24
+ index_rows = []
25
+ uv_rows = []
26
+
27
+ for y in 0..height_segments do
28
+ index_row = []
29
+ uv_row = []
30
+
31
+ v = y.to_f / height_segments.to_f
32
+ radius = v * (radius_bottom - radius_top) + radius_top
33
+
34
+ for x in 0..radial_segments do
35
+ u = x.to_f / radial_segments
36
+
37
+ vertex = Vector3.new
38
+ vertex.x = radius * ::Math.sin(u * theta_length + theta_start)
39
+ vertex.y = -v * height + height_half
40
+ vertex.z = radius * ::Math.cos(u * theta_length + theta_start)
41
+
42
+ @vertices << vertex
43
+
44
+ index_row << (vertices.length - 1)
45
+ uv_row << Vector2.new(u, 1.0 - v)
46
+ end
47
+
48
+ index_rows << index_row
49
+ uv_rows << uv_row
50
+ end
51
+
52
+ tan_theta = (radius_bottom - radius_top) / height
53
+
54
+ na = nil
55
+ nb = nil
56
+
57
+ for x in 0...radial_segments do
58
+ if radius_top != 0
59
+ na = @vertices[index_rows[0][x]].clone
60
+ nb = @vertices[index_rows[0][x + 1]].clone
61
+ else
62
+ na = @vertices[index_rows[1][x]].clone
63
+ nb = @vertices[index_rows[1][x + 1]].clone
64
+ end
65
+
66
+ na.y = ::Math.sqrt(na.x * na.x + na.z * na.z) * tan_theta
67
+ na.normalize
68
+
69
+ nb.y = ::Math.sqrt(nb.x * nb.x + nb.z * nb.z) * tan_theta
70
+ nb.normalize
71
+
72
+ for y in 0...height_segments do
73
+ v1 = index_rows[y][x]
74
+ v2 = index_rows[y + 1][x]
75
+ v3 = index_rows[y + 1][x + 1]
76
+ v4 = index_rows[y][x + 1]
77
+
78
+ n1 = na.clone
79
+ n2 = na.clone
80
+ n3 = nb.clone
81
+ n4 = nb.clone
82
+
83
+ uv1 = uv_rows[y][x].clone
84
+ uv2 = uv_rows[y + 1][x].clone
85
+ uv3 = uv_rows[y + 1][x + 1].clone
86
+ uv4 = uv_rows[y][x + 1].clone
87
+
88
+ @faces << Face3.new(v1, v2, v4, [n1, n2, n4])
89
+ @face_vertex_uvs[0] << [uv1, uv2, uv4]
90
+
91
+ @faces << Face3.new(v2, v3, v4, [n2.clone, n3, n4.clone])
92
+ @face_vertex_uvs[0] << [uv2.clone, uv3, uv4.clone]
93
+ end
94
+ end
95
+
96
+ # top cap
97
+
98
+ if !open_ended && radius_top > 0.0
99
+ @vertices << Vector3.new(0, height_half, 0)
100
+
101
+ for x in 0...radial_segments do
102
+ v1 = index_rows[0][x]
103
+ v2 = index_rows[0][x + 1]
104
+ v3 = @vertices.length - 1
105
+
106
+ n1 = Vector3.new(0, 1, 0)
107
+ n2 = Vector3.new(0, 1, 0)
108
+ n3 = Vector3.new(0, 1, 0)
109
+
110
+ uv1 = uv_rows[0][x].clone
111
+ uv2 = uv_rows[0][x + 1].clone
112
+ uv3 = Vector2.new(uv2.x, 0)
113
+
114
+ @faces << Face3.new(v1, v2, v3, [n1, n2, n3])
115
+ @face_vertex_uvs[0] << [uv1, uv2, uv3]
116
+ end
117
+ end
118
+
119
+ # bottom cap
120
+
121
+ if !open_ended && radius_bottom > 0.0
122
+ @vertices << Vector3.new(0, -height_half, 0)
123
+
124
+ for x in 0...radial_segments do
125
+ v1 = index_rows[height_segments][x + 1]
126
+ v2 = index_rows[height_segments][x]
127
+ v3 = @vertices.length - 1
128
+
129
+ n1 = Vector3.new(0, -1, 0)
130
+ n2 = Vector3.new(0, -1, 0)
131
+ n3 = Vector3.new(0, -1, 0)
132
+
133
+ uv1 = uv_rows[height_segments][x].clone
134
+ uv2 = uv_rows[height_segments][x + 1].clone
135
+ uv3 = Vector2.new(uv2.x, 0)
136
+
137
+ @faces << Face3.new(v1, v2, v3, [n1, n2, n3])
138
+ @face_vertex_uvs[0] << [uv1, uv2, uv3]
139
+ end
140
+ end
141
+
142
+ compute_face_normals
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,56 @@
1
+ require 'mittsu/core'
2
+ require 'mittsu/math'
3
+ require 'mittsu/extras/geometries/polyhedron_geometry'
4
+
5
+ module Mittsu
6
+ class DodecahedronGeometry < PolyhedronGeometry
7
+ def initialize(radius = 1.0, detail = 0)
8
+ t = (1.0 + ::Math.sqrt(5.0)) / 2.0
9
+ r = 1.0 / t
10
+
11
+ vertices = [
12
+ # (±1, ±1, ±1)
13
+ -1, -1, -1, -1, -1, 1,
14
+ -1, 1, -1, -1, 1, 1,
15
+ 1, -1, -1, 1, -1, 1,
16
+ 1, 1, -1, 1, 1, 1,
17
+
18
+ # (0, ±1/φ, ±φ)
19
+ 0, -r, -t, 0, -r, t,
20
+ 0, r, -t, 0, r, t,
21
+
22
+ # (±1/φ, ±φ, 0)
23
+ -r, -t, 0, -r, t, 0,
24
+ r, -t, 0, r, t, 0,
25
+
26
+ # (±φ, 0, ±1/φ)
27
+ -t, 0, -r, t, 0, -r,
28
+ -t, 0, r, t, 0, r
29
+ ]
30
+
31
+ indices = [
32
+ 3, 11, 7, 3, 7, 15, 3, 15, 13,
33
+ 7, 19, 17, 7, 17, 6, 7, 6, 15,
34
+ 17, 4, 8, 17, 8, 10, 17, 10, 6,
35
+ 8, 0, 16, 8, 16, 2, 8, 2, 10,
36
+ 0, 12, 1, 0, 1, 18, 0, 18, 16,
37
+ 6, 10, 2, 6, 2, 13, 6, 13, 15,
38
+ 2, 16, 18, 2, 18, 3, 2, 3, 13,
39
+ 18, 1, 9, 18, 9, 11, 18, 11, 3,
40
+ 4, 14, 12, 4, 12, 0, 4, 0, 8,
41
+ 11, 9, 5, 11, 5, 19, 11, 19, 7,
42
+ 19, 5, 14, 19, 14, 4, 19, 4, 17,
43
+ 1, 12, 14, 1, 14, 5, 1, 5, 9
44
+ ]
45
+
46
+ super(vertices, indices, radius, detail)
47
+
48
+ @type = 'DodecahedronGeometry'
49
+
50
+ @parameters = {
51
+ radius: radius,
52
+ detail: detail
53
+ }
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,33 @@
1
+ require 'mittsu/core'
2
+ require 'mittsu/math'
3
+ require 'mittsu/extras/geometries/polyhedron_geometry'
4
+
5
+ module Mittsu
6
+ class IcosahedronGeometry < PolyhedronGeometry
7
+ def initialize(radius = 1.0, detail = 0)
8
+ t = (1.0 + ::Math.sqrt(5)) / 2.0
9
+
10
+ vertices = [
11
+ - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0,
12
+ 0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t,
13
+ t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1
14
+ ]
15
+
16
+ indices = [
17
+ 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11,
18
+ 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
19
+ 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9,
20
+ 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1
21
+ ]
22
+
23
+ super(vertices, indices, radius, detail)
24
+
25
+ @type = 'IcosahedronGeometry'
26
+
27
+ @parameters = {
28
+ radius: radius,
29
+ detail: detail
30
+ }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,78 @@
1
+ require 'mittsu/core'
2
+ require 'mittsu/math'
3
+
4
+ module Mittsu
5
+ class LatheGeometry < Geometry
6
+ def initialize(points, segments = 12, phi_start = 0.0, phi_length = (::Math::PI * 2.0))
7
+ super()
8
+
9
+ @type = 'LatheGeometry'
10
+
11
+ @parameters = {
12
+ points: points,
13
+ segments: segments,
14
+ phi_start: phi_start,
15
+ phi_length: phi_length
16
+ }
17
+
18
+ inverse_point_length = 1.0 / (points.length.to_f - 1.0)
19
+ inverse_segments = 1.0 / segments.to_f
20
+
21
+ for i in 0..segments do
22
+ phi = phi_start + i.to_f * inverse_segments * phi_length
23
+
24
+ c = ::Math.cos(phi)
25
+ s = ::Math.sin(phi)
26
+
27
+ for j in 0...points.length do
28
+ pt = points[j]
29
+
30
+ vertex = Vector3.new
31
+
32
+ vertex.x = c * pt.x
33
+ vertex.y = pt.y
34
+ vertex.z = s * pt.x
35
+
36
+ @vertices << vertex
37
+ end
38
+ end
39
+
40
+ np = points.length
41
+
42
+ for i in 0...segments do
43
+ for j in 0...(points.length - 1) do
44
+ base = j + np * i
45
+ a = base
46
+ b = base + np
47
+ c = base + 1 + np
48
+ d = base + 1
49
+
50
+ u0 = i.to_f * inverse_segments
51
+ v0 = j.to_f * inverse_point_length
52
+ u1 = u0 + inverse_segments
53
+ v1 = v0 + inverse_point_length
54
+
55
+ @faces << Face3.new(a, b, d)
56
+
57
+ @face_vertex_uvs[0] << [
58
+ Vector2.new(u0, v0),
59
+ Vector2.new(u1, v0),
60
+ Vector2.new(u0, v1)
61
+ ]
62
+
63
+ @faces << Face3.new(b, c, d)
64
+
65
+ @face_vertex_uvs[0] << [
66
+ Vector2.new(u1, v0),
67
+ Vector2.new(u1, v1),
68
+ Vector2.new(u0, v1)
69
+ ]
70
+ end
71
+ end
72
+
73
+ merge_vertices
74
+ compute_face_normals
75
+ compute_vertex_normals
76
+ end
77
+ end
78
+ end
@@ -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 OctahedronGeometry < PolyhedronGeometry
7
+ def initialize(radius = 1.0, detail = 0)
8
+ vertices = [
9
+ 1, 0, 0, - 1, 0, 0, 0, 1, 0, 0,- 1, 0, 0, 0, 1, 0, 0,- 1
10
+ ]
11
+
12
+ indices = [
13
+ 0, 2, 4, 0, 4, 3, 0, 3, 5, 0, 5, 2, 1, 2, 5, 1, 5, 3, 1, 3, 4, 1, 4, 2
14
+ ]
15
+
16
+ super(vertices, indices, radius, detail)
17
+
18
+ @type = 'OctahedronGeometry'
19
+
20
+ @parameters = {
21
+ radius: radius,
22
+ detail: detail
23
+ }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,92 @@
1
+ module Mittsu
2
+ class ParametricBufferGeometry < BufferGeometry
3
+ EPS = 0.00001
4
+
5
+ def initialize(func, slices, stacks)
6
+ super()
7
+
8
+ @type = 'ParametricBufferGeometry'
9
+
10
+ @parameters = {
11
+ func: func,
12
+ slices: slices,
13
+ stacks: stacks
14
+ }
15
+
16
+ # buffers
17
+
18
+ indices = []
19
+ vertices = []
20
+ normals = []
21
+ uvs = []
22
+
23
+ normal = Vector3.new
24
+
25
+ p0 = Vector3.new
26
+ p1 = Vector3.new
27
+
28
+ pu = Vector3.new
29
+ pv = Vector3.new
30
+
31
+ # generate vertices, normals, and uvs
32
+
33
+ slice_count = slices + 1
34
+
35
+ for i in 0..stacks do
36
+ v = i.to_f / stacks.to_f
37
+
38
+ for j in 0..slices do
39
+ u = j.to_f / slices.to_f
40
+
41
+ # vertex
42
+ func.call(u, v, p0)
43
+ vertices += p0.elements
44
+
45
+ # normal
46
+
47
+ # approximate tangent vectors via finite differences
48
+ if u - EPS >= 0
49
+ func.call(u - EPS, v, p1)
50
+ pu.sub_vectors(p0, p1)
51
+ else
52
+ func.call(u + EPS, v, p1)
53
+ pu.sub_vectors(p1, p0)
54
+ end
55
+
56
+ if v - EPS >= 0
57
+ func.call(u, v - EPS, p1)
58
+ pv.sub_vectors(p0, p1)
59
+ else
60
+ func.call(u, v + EPS, p1)
61
+ pv.sub_vectors(p1, p0)
62
+ end
63
+
64
+ # cross product of tangent vectors returns surface normal
65
+ normal.cross_vectors(pu, pv).normalize
66
+ normals += normal.elements
67
+
68
+ # uv
69
+ uvs << u << v
70
+ end
71
+ end
72
+
73
+ for i in 0...stacks do
74
+ for j in 0...slices do
75
+ a = i * slice_count + j
76
+ b = i * slice_count + j + 1
77
+ c = (i + 1) * slice_count + j + 1
78
+ d = (i + 1) * slice_count + j
79
+
80
+ # faces one and two
81
+ indices << a << b << d
82
+ indices << b << c << d
83
+ end
84
+ end
85
+
86
+ self[:index] = BufferAttribute.new(indices, 1)
87
+ self[:position] = BufferAttribute.new(vertices, 3)
88
+ self[:normal] = BufferAttribute.new(normals, 3)
89
+ self[:uv] = BufferAttribute.new(uvs, 2)
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,93 @@
1
+ require 'mittsu/extras/geometries/parametric_buffer_geometry'
2
+
3
+ module Mittsu
4
+ class ParametricGeometry < Geometry
5
+ def initialize(func, slices, stacks)
6
+ super()
7
+
8
+ @type = 'ParametricGeometry'
9
+
10
+ @parameters = {
11
+ func: func,
12
+ slices: slices,
13
+ stacks: stacks
14
+ }
15
+
16
+ from_buffer_geometry(ParametricBufferGeometry.new(func, slices, stacks))
17
+ merge_vertices
18
+ end
19
+
20
+ def self.klein
21
+ -> (v, u, target = Vector3.new) {
22
+ u *= ::Math::PI
23
+ v *= 2.0 * ::Math::PI
24
+
25
+ u = u * 2.0
26
+ x = nil
27
+ y = nil
28
+ z = nil
29
+
30
+ if u < ::Math::PI
31
+ x = 3.0 * ::Math.cos(u) * (1.0 + ::Math.sin(u)) + (2.0 * (1.0 - ::Math.cos(u) / 2.0)) * ::Math.cos(u) * ::Math.cos(v)
32
+ z = -8.0 * ::Math.sin(u) - 2.0 * (1.0 - ::Math.cos(u) / 2.0) * ::Math.sin(u) * ::Math.cos(v)
33
+ else
34
+ x = 3.0 * ::Math.cos(u) * (1.0 + ::Math.sin(u)) + (2.0 * (1.0 - ::Math.cos(u) / 2.0)) * ::Math.cos(v + ::Math::PI)
35
+ z = -8.0 * ::Math.sin(u)
36
+ end
37
+
38
+ y = -2.0 * (1.0 - ::Math.cos(u) / 2.0) * ::Math.sin(v)
39
+
40
+ target.set(x, y, z)
41
+ }
42
+ end
43
+
44
+ def self.plane(width, height)
45
+ -> (u, v, target = Vector3.new) {
46
+ x = u.to_f * width.to_f
47
+ y = 0.0
48
+ z = v.to_f * height.to_f
49
+
50
+ target.set(x, y, z)
51
+ }
52
+ end
53
+
54
+ def self.mobius
55
+ -> (u, t, target = Vector3.new) {
56
+ # flat mobius strip
57
+ # http://www.wolframalpha.com/input/?i=M%C3%B6bius+strip+parametric+equations&lk=1&a=ClashPrefs_*Surface.MoebiusStrip.SurfaceProperty.ParametricEquations-
58
+ u = u - 0.5
59
+ v = 2.0 * ::Math::PI * t
60
+
61
+ a = 2.0
62
+
63
+ x = ::Math.cos(v) * (a + u * ::Math.cos(v / 2.0))
64
+ y = ::Math.sin(v) * (a + u * ::Math.cos(v / 2.0))
65
+ z = u * ::Math.sin(v / 2)
66
+
67
+ target.set(x, y, z)
68
+ }
69
+ end
70
+
71
+ def self.mobius3d
72
+ -> (u, t, target = Vector3.new) {
73
+ # volumetric mobius strip
74
+
75
+ u *= ::Math::PI
76
+ t *= 2.0 * ::Math::PI
77
+
78
+ u = u * 2.0
79
+ phi = u / 2.0
80
+ major = 2.25
81
+ a = 0.125
82
+ b = 0.65
83
+
84
+ x = a * ::Math.cos(t) * ::Math.cos(phi) - b * ::Math.sin(t) * ::Math.sin(phi)
85
+ z = a * ::Math.cos(t) * ::Math.sin(phi) + b * ::Math.sin(t) * ::Math.cos(phi)
86
+ y = (major + x) * ::Math.sin(u)
87
+ x = (major + x) * ::Math.cos(u)
88
+
89
+ target.set(x, y, z)
90
+ }
91
+ end
92
+ end
93
+ end