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.
- checksums.yaml +4 -4
- data/.github/workflows/build-workflow.yml +95 -0
- data/.gitignore +1 -0
- data/Gemfile +3 -2
- data/README.md +3 -7
- data/Rakefile +1 -0
- data/install-glfw.ps1 +13 -0
- data/lib/mittsu.rb +1 -16
- data/lib/mittsu/cameras/camera.rb +0 -2
- data/lib/mittsu/cameras/cube_camera.rb +0 -2
- data/lib/mittsu/cameras/orthographic_camera.rb +2 -4
- data/lib/mittsu/cameras/perspective_camera.rb +4 -5
- data/lib/mittsu/core/buffer_geometry.rb +3 -3
- data/lib/mittsu/core/geometry.rb +10 -9
- data/lib/mittsu/core/object_3d.rb +9 -7
- data/lib/mittsu/core/raycaster.rb +0 -2
- data/lib/mittsu/extras/geometries.rb +13 -0
- data/lib/mittsu/extras/geometries/circle_geometry.rb +48 -0
- data/lib/mittsu/extras/geometries/cylinder_geometry.rb +145 -0
- data/lib/mittsu/extras/geometries/dodecahedron_geometry.rb +56 -0
- data/lib/mittsu/extras/geometries/icosahedron_geometry.rb +33 -0
- data/lib/mittsu/extras/geometries/lathe_geometry.rb +78 -0
- data/lib/mittsu/extras/geometries/octahedron_geometry.rb +26 -0
- data/lib/mittsu/extras/geometries/parametric_buffer_geometry.rb +92 -0
- data/lib/mittsu/extras/geometries/parametric_geometry.rb +93 -0
- data/lib/mittsu/extras/geometries/plane_buffer_geometry.rb +81 -0
- data/lib/mittsu/extras/geometries/plane_geometry.rb +22 -0
- data/lib/mittsu/extras/geometries/polyhedron_geometry.rb +168 -0
- data/lib/mittsu/extras/geometries/ring_geometry.rb +80 -0
- data/lib/mittsu/extras/geometries/sphere_geometry.rb +4 -4
- data/lib/mittsu/extras/geometries/tetrahedron_geometry.rb +26 -0
- data/lib/mittsu/extras/geometries/torus_geometry.rb +63 -0
- data/lib/mittsu/extras/geometries/torus_knot_buffer_geometry.rb +120 -0
- data/lib/mittsu/extras/geometries/torus_knot_geometry.rb +25 -0
- data/lib/mittsu/extras/helpers/camera_helper.rb +38 -38
- data/lib/mittsu/extras/image_utils.rb +1 -1
- data/lib/mittsu/lights/directional_light.rb +9 -5
- data/lib/mittsu/lights/spot_light.rb +1 -1
- data/lib/mittsu/loaders/loader.rb +2 -2
- data/lib/mittsu/loaders/obj_loader.rb +4 -0
- data/lib/mittsu/materials/material.rb +6 -3
- data/lib/mittsu/math.rb +0 -5
- data/lib/mittsu/math/box2.rb +0 -2
- data/lib/mittsu/math/box3.rb +0 -2
- data/lib/mittsu/math/color.rb +3 -4
- data/lib/mittsu/math/euler.rb +25 -26
- data/lib/mittsu/math/frustum.rb +0 -2
- data/lib/mittsu/math/line3.rb +0 -2
- data/lib/mittsu/math/matrix3.rb +0 -2
- data/lib/mittsu/math/matrix4.rb +10 -12
- data/lib/mittsu/math/plane.rb +0 -2
- data/lib/mittsu/math/quaternion.rb +18 -20
- data/lib/mittsu/math/ray.rb +1 -3
- data/lib/mittsu/math/sphere.rb +1 -3
- data/lib/mittsu/math/spline.rb +0 -2
- data/lib/mittsu/math/triangle.rb +1 -3
- data/lib/mittsu/math/vector.rb +4 -4
- data/lib/mittsu/math/vector2.rb +0 -1
- data/lib/mittsu/math/vector3.rb +0 -1
- data/lib/mittsu/math/vector4.rb +8 -9
- data/lib/mittsu/objects/line.rb +0 -1
- data/lib/mittsu/renderers/glfw_lib.rb +1 -1
- data/lib/mittsu/renderers/glfw_window.rb +1 -1
- data/lib/mittsu/renderers/opengl/core/object_3d.rb +1 -1
- data/lib/mittsu/renderers/opengl/lights/spot_light.rb +1 -1
- data/lib/mittsu/renderers/opengl/opengl_geometry_group.rb +1 -0
- data/lib/mittsu/renderers/opengl/opengl_program.rb +1 -2
- data/lib/mittsu/renderers/opengl/textures/texture.rb +1 -1
- data/lib/mittsu/renderers/opengl_renderer.rb +5 -10
- data/lib/mittsu/scenes/scene.rb +0 -2
- data/lib/mittsu/textures/texture.rb +4 -2
- data/lib/mittsu/utils.rb +15 -0
- data/lib/mittsu/version.rb +1 -1
- data/mittsu.gemspec +10 -9
- metadata +75 -47
- data/.circleci/config.yml +0 -44
- data/.travis.yml +0 -20
- data/appveyor.yml +0 -23
- 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
|