mittsu 0.2.4 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: db458484a3c4620067a0a3d7c58751e0a7588cbb4320f10be9ed49441db5ba07
4
- data.tar.gz: 8af94bffbd0c624f0b5e676e9da2b5e72de09eaf3f921d9650617b56e84fad5d
3
+ metadata.gz: 1d75b0ef6c6615fff22f50ab9f3bc438e5c2631d5924f30da913df6403d5ccd0
4
+ data.tar.gz: 4656d50526e5be69dd19f3f0de87b4f93de5ad0a2e664b6277b023b885d7c3a0
5
5
  SHA512:
6
- metadata.gz: f45a750a1557b6f9fdbe46a1cb652b9d6e731294da4d00af0602ec2d64f0fbb47c63dba9ec249f94c006ebbe76066d67dad50c6c94ca066c0d376e9dd38f67ee
7
- data.tar.gz: d3f6931cf6301e53bcbc2296213fc1da27996f46d6211a4d949af16ecc1489cd2e909a5ce6b934b6c3cad55ad21beb81c71c92cea63625146d8b1a38a9d99b1d
6
+ metadata.gz: 4093db783cef7214c92fa5ce723cf84466a4dcd30d1e7a8fe6c5b9ff41f4be13d04eaeb072e30e6e039191d410303adf47c55288429439412e746ba300e05918
7
+ data.tar.gz: e3bafbb95cff8e606f36e6e456314a75cbfc9c0284022ef73258d40316918fd87dce5b11b21aa1b25802a071b91b413df53de8220f1294eadf892600f79868fd
@@ -1,5 +1,6 @@
1
1
  require 'securerandom'
2
2
  require 'mittsu'
3
+ require 'securerandom'
3
4
 
4
5
  module Mittsu
5
6
  class Geometry
@@ -19,6 +20,8 @@ module Mittsu
19
20
 
20
21
  @id = (@@id ||= 1).tap { @@id += 1 }
21
22
 
23
+ @uuid = SecureRandom.uuid
24
+
22
25
  @name = ''
23
26
  @type = 'Geometry'
24
27
 
@@ -105,7 +108,7 @@ module Mittsu
105
108
  }
106
109
  if indices
107
110
  draw_calls = geometry.draw_calls
108
- if !draw_calls.length.empty?
111
+ if !draw_calls.empty?
109
112
  draw_calls.each do |draw_call|
110
113
  start = draw_call.start
111
114
  count = draw_call.count
@@ -119,7 +122,7 @@ module Mittsu
119
122
  end
120
123
  else
121
124
  indices.each_slice(3).with_index do |index|
122
- add_face(*index)
125
+ add_face[*index]
123
126
  end
124
127
  end
125
128
  else
@@ -130,10 +133,10 @@ module Mittsu
130
133
  end
131
134
  end
132
135
  self.compute_face_normals
133
- if geometry.boundingBox
136
+ if geometry.bounding_box
134
137
  @bounding_box = geometry.bounding_box.clone
135
138
  end
136
- if geometry.boundingSphere
139
+ if geometry.bounding_sphere
137
140
  @bounding_sphere = geometry.bounding_sphere.clone
138
141
  end
139
142
  self
@@ -160,12 +163,12 @@ module Mittsu
160
163
  end
161
164
  end
162
165
 
163
- def compute_vertex_normals(area_weigted)
166
+ def compute_vertex_normals(area_weighted = false)
164
167
  vertices = Array.new(@vertices.length)
165
168
  @vertices.length.times do |v|
166
169
  vertices[v] = Mittsu::Vector3.new
167
170
  end
168
- if area_weigted
171
+ if area_weighted
169
172
  # vertex normals weighted by triangle areas
170
173
  # http:#www.iquilezles.org/www/articles/normals/normals.htm
171
174
  cb = Mittsu::Vector3.new, ab = Mittsu::Vector3.new
@@ -1,2 +1,15 @@
1
1
  require 'mittsu/extras/geometries/box_geometry'
2
2
  require 'mittsu/extras/geometries/sphere_geometry'
3
+ require 'mittsu/extras/geometries/ring_geometry'
4
+ require 'mittsu/extras/geometries/circle_geometry'
5
+ require 'mittsu/extras/geometries/cylinder_geometry'
6
+ require 'mittsu/extras/geometries/dodecahedron_geometry'
7
+ require 'mittsu/extras/geometries/icosahedron_geometry'
8
+ require 'mittsu/extras/geometries/octahedron_geometry'
9
+ require 'mittsu/extras/geometries/tetrahedron_geometry'
10
+ require 'mittsu/extras/geometries/plane_buffer_geometry'
11
+ require 'mittsu/extras/geometries/plane_geometry'
12
+ require 'mittsu/extras/geometries/torus_geometry'
13
+ require 'mittsu/extras/geometries/torus_knot_geometry'
14
+ require 'mittsu/extras/geometries/parametric_geometry'
15
+ require 'mittsu/extras/geometries/lathe_geometry'
@@ -0,0 +1,48 @@
1
+ require 'mittsu/core'
2
+ require 'mittsu/math'
3
+
4
+ module Mittsu
5
+ class CircleGeometry < Geometry
6
+ def initialize(radius = 50.0, segments = 8, theta_start = 0.0, theta_length = (Math::PI * 2.0))
7
+ super()
8
+
9
+ @type = 'CircleGeometry'
10
+
11
+ @parameters = {
12
+ radius: radius,
13
+ segments: segments,
14
+ theta_start: theta_start,
15
+ theta_length: theta_length
16
+ }
17
+
18
+ segments = [3, segments].max
19
+
20
+ center = Vector3.new
21
+ center_uv = Vector2.new(0.5, 0.5)
22
+
23
+ @vertices << center
24
+ uvs = [center_uv]
25
+
26
+ for i in 0..segments do
27
+ vertex = Vector3.new
28
+ segment = theta_start + i.to_f / segments.to_f * theta_length
29
+
30
+ vertex.x = radius * Math.cos(segment)
31
+ vertex.y = radius * Math.sin(segment)
32
+
33
+ @vertices << vertex
34
+ uvs << Vector2.new((vertex.x / radius + 1.0) / 2.0, (vertex.y / radius + 1.0) / 2.0)
35
+ end
36
+
37
+ n = Vector3.new
38
+
39
+ for i in 1..segments do
40
+ @faces << Face3.new(i, i + 1, 0, [n.clone, n.clone, n.clone])
41
+ @face_vertex_uvs[0] << [uvs[i].clone, uvs[i + 1].clone, center_uv.clone]
42
+ end
43
+
44
+ compute_face_normals
45
+ @bounding_sphere = Sphere.new(Vector3.new, radius)
46
+ end
47
+ end
48
+ end
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,120 @@
1
+ module Mittsu
2
+ class TorusKnotBufferGeometry < BufferGeometry
3
+ def initialize(radius = 100.0, tube = 40.0, radial_segments = 64, tubular_segments = 8, p_val = 2, q_val = 3)
4
+ super()
5
+
6
+ @type = 'TorusKnotBufferGeometry'
7
+
8
+ @parameters = {
9
+ radius: radius,
10
+ tube: tube,
11
+ radial_segments: radial_segments,
12
+ tubular_segments: tubular_segments,
13
+ p_val: p_val,
14
+ q_val: q_val
15
+ }
16
+
17
+ # buffers
18
+
19
+ indices = []
20
+ vertices = []
21
+ normals = []
22
+ uvs = []
23
+
24
+ # helper variables
25
+
26
+ vertex = Vector3.new
27
+ normal = Vector3.new
28
+
29
+ p1 = Vector3.new
30
+ p2 = Vector3.new
31
+
32
+ b = Vector3.new
33
+ t = Vector3.new
34
+ n = Vector3.new
35
+
36
+ # generate vertices, normals and uvs
37
+
38
+ for i in 0..tubular_segments do
39
+ # the radian "u" is used to calculate the position on the torus curve of the current tubular segement
40
+ u = i.to_f / tubular_segments.to_f * p_val.to_f * Math::PI * 2.0
41
+
42
+ # now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
43
+ # these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
44
+ calculate_position_on_curve(u, p_val, q_val, radius, p1)
45
+ calculate_position_on_curve(u + 0.01, p_val, q_val, radius, p2)
46
+
47
+ # calculate orthonormal basis
48
+ t.sub_vectors(p2, p1)
49
+ n.add_vectors(p2, p1)
50
+ b.cross_vectors(t, n)
51
+ n.cross_vectors(b, t)
52
+
53
+ # normalize B, N. T can be ignored, we don't use it
54
+ b.normalize
55
+ n.normalize
56
+
57
+ for j in 0..radial_segments do
58
+ # now calculate the vertices. they are nothing more than an extrusion of the torus curve.
59
+ # because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
60
+ v = j.to_f / radial_segments.to_f * Math::PI * 2.0
61
+ cx = -tube * Math.cos(v)
62
+ cy = tube * Math.sin(v)
63
+
64
+ # now calculate the final vertex position.
65
+ # first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
66
+ vertex.x = p1.x + (cx * n.x + cy * b.x)
67
+ vertex.y = p1.y + (cx * n.y + cy * b.y)
68
+ vertex.z = p1.z + (cx * n.z + cy * b.z)
69
+
70
+ vertices += vertex.elements
71
+
72
+ # normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
73
+ normal.sub_vectors(vertex, p1).normalize
74
+
75
+ normals += normal.elements
76
+
77
+ # uv
78
+ uvs << i.to_f / tubular_segments.to_f
79
+ uvs << j.to_f / radial_segments.to_f
80
+ end
81
+ end
82
+
83
+ # generate indices
84
+
85
+ for j in 1..tubular_segments do
86
+ for i in 1..radial_segments do
87
+ # indices
88
+ a = (radial_segments + 1) * (j - 1) + (i - 1)
89
+ b = (radial_segments + 1) * j + (i - 1)
90
+ c = (radial_segments + 1) * j + i
91
+ d = (radial_segments + 1) * (j - 1) + i
92
+
93
+ # faces
94
+ indices += [a, b, d]
95
+ indices += [b, c, d]
96
+ end
97
+ end
98
+
99
+ # build geometry
100
+
101
+ self[:index] = BufferAttribute.new(indices, 1)
102
+ self[:position] = BufferAttribute.new(vertices, 3)
103
+ self[:normal] = BufferAttribute.new(normals, 3)
104
+ self[:uv] = BufferAttribute.new(uvs, 2)
105
+ end
106
+
107
+ private
108
+
109
+ def calculate_position_on_curve(u, p_val, q_val, radius, position)
110
+ cu = Math.cos(u)
111
+ su = Math.sin(u)
112
+ qu_over_p = q_val.to_f / p_val.to_f * u
113
+ cs = Math.cos(qu_over_p)
114
+
115
+ position.x = radius * (2.0 + cs) * 0.5 * cu
116
+ position.y = radius * (2.0 + cs) * su * 0.5
117
+ position.z = radius * Math.sin(qu_over_p) * 0.5
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,25 @@
1
+ require 'mittsu/core'
2
+ require 'mittsu/math'
3
+ require 'mittsu/extras/geometries/torus_knot_buffer_geometry'
4
+
5
+ module Mittsu
6
+ class TorusKnotGeometry < Geometry
7
+ def initialize(radius = 100.0, tube = 40.0, radial_segments = 64, tubular_segments = 8, p_val = 2, q_val = 3)
8
+ super()
9
+
10
+ @type = 'TorusKnotGeometry'
11
+
12
+ @parameters = {
13
+ radius: radius,
14
+ tube: tube,
15
+ radial_segments: radial_segments,
16
+ tubular_segments: tubular_segments,
17
+ p_val: p_val,
18
+ q_val: q_val
19
+ }
20
+
21
+ from_buffer_geometry(TorusKnotBufferGeometry.new(radius, tube, tubular_segments, radial_segments, p_val, q_val))
22
+ merge_vertices
23
+ end
24
+ end
25
+ end
@@ -1,6 +1,6 @@
1
1
  module Mittsu
2
2
  class Vector
3
- attr_accessor :elements
3
+ attr_accessor :elements, :uv, :index
4
4
 
5
5
  def initialize(elements)
6
6
  @elements = elements
@@ -1,4 +1,4 @@
1
1
  module Mittsu
2
- VERSION = "0.2.4"
2
+ VERSION = "0.3.0"
3
3
  REVISION = "71"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mittsu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Smith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-16 00:00:00.000000000 Z
11
+ date: 2018-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opengl-bindings
@@ -181,7 +181,23 @@ files:
181
181
  - lib/mittsu/extras.rb
182
182
  - lib/mittsu/extras/geometries.rb
183
183
  - lib/mittsu/extras/geometries/box_geometry.rb
184
+ - lib/mittsu/extras/geometries/circle_geometry.rb
185
+ - lib/mittsu/extras/geometries/cylinder_geometry.rb
186
+ - lib/mittsu/extras/geometries/dodecahedron_geometry.rb
187
+ - lib/mittsu/extras/geometries/icosahedron_geometry.rb
188
+ - lib/mittsu/extras/geometries/lathe_geometry.rb
189
+ - lib/mittsu/extras/geometries/octahedron_geometry.rb
190
+ - lib/mittsu/extras/geometries/parametric_buffer_geometry.rb
191
+ - lib/mittsu/extras/geometries/parametric_geometry.rb
192
+ - lib/mittsu/extras/geometries/plane_buffer_geometry.rb
193
+ - lib/mittsu/extras/geometries/plane_geometry.rb
194
+ - lib/mittsu/extras/geometries/polyhedron_geometry.rb
195
+ - lib/mittsu/extras/geometries/ring_geometry.rb
184
196
  - lib/mittsu/extras/geometries/sphere_geometry.rb
197
+ - lib/mittsu/extras/geometries/tetrahedron_geometry.rb
198
+ - lib/mittsu/extras/geometries/torus_geometry.rb
199
+ - lib/mittsu/extras/geometries/torus_knot_buffer_geometry.rb
200
+ - lib/mittsu/extras/geometries/torus_knot_geometry.rb
185
201
  - lib/mittsu/extras/helpers.rb
186
202
  - lib/mittsu/extras/helpers/camera_helper.rb
187
203
  - lib/mittsu/extras/image.rb