Class: Mittsu::TorusKnotBufferGeometry

Inherits:
BufferGeometry show all
Defined in:
lib/mittsu/extras/geometries/torus_knot_buffer_geometry.rb

Instance Attribute Summary

Attributes inherited from BufferGeometry

#attributes, #bounding_box, #bounding_sphere, #draw_calls, #id, #name, #type, #uuid

Instance Method Summary collapse

Methods inherited from BufferGeometry

#[], #[]=, #add_draw_call, #apply_matrix, #center, #clone, #compute_bounding_box, #compute_bounding_sphere, #compute_offsets, #compute_tangents, #compute_vertex_normals, #dispose, #from_geometry, #keys, #merge, #normalize_normals, #reorder_buffers, #to_json

Methods included from EventDispatcher

#add_event_listener, #dispatch_event, #has_event_listener, #remove_event_listener

Constructor Details

#initialize(radius = 100.0, tube = 40.0, radial_segments = 64, tubular_segments = 8, p_val = 2, q_val = 3) ⇒ TorusKnotBufferGeometry

Returns a new instance of TorusKnotBufferGeometry.



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/mittsu/extras/geometries/torus_knot_buffer_geometry.rb', line 3

def initialize(radius = 100.0, tube = 40.0, radial_segments = 64, tubular_segments = 8, p_val = 2, q_val = 3)
  super()

  @type = 'TorusKnotBufferGeometry'

  @parameters = {
    radius:           radius,
    tube:             tube,
    radial_segments:  radial_segments,
    tubular_segments: tubular_segments,
    p_val:            p_val,
    q_val:            q_val
  }

  # buffers

  indices = []
  vertices = []
  normals = []
  uvs = []

  # helper variables

  vertex = Vector3.new
  normal = Vector3.new

  p1 = Vector3.new
  p2 = Vector3.new

  b = Vector3.new
  t = Vector3.new
  n = Vector3.new

  # generate vertices, normals and uvs

  for i in 0..tubular_segments do
    # the radian "u" is used to calculate the position on the torus curve of the current tubular segement
    u = i.to_f / tubular_segments.to_f * p_val.to_f * ::Math::PI * 2.0

    # now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
    # these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
    calculate_position_on_curve(u,        p_val, q_val, radius, p1)
    calculate_position_on_curve(u + 0.01, p_val, q_val, radius, p2)

    # calculate orthonormal basis
    t.sub_vectors(p2, p1)
    n.add_vectors(p2, p1)
    b.cross_vectors(t, n)
    n.cross_vectors(b, t)

    # normalize B, N. T can be ignored, we don't use it
    b.normalize
    n.normalize

    for j in 0..radial_segments do
      # now calculate the vertices. they are nothing more than an extrusion of the torus curve.
      # because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
      v = j.to_f / radial_segments.to_f * ::Math::PI * 2.0
      cx = -tube * ::Math.cos(v)
      cy = tube * ::Math.sin(v)

      # now calculate the final vertex position.
      # first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
      vertex.x = p1.x + (cx * n.x + cy * b.x)
      vertex.y = p1.y + (cx * n.y + cy * b.y)
      vertex.z = p1.z + (cx * n.z + cy * b.z)

      vertices += vertex.elements

      # normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
      normal.sub_vectors(vertex, p1).normalize
      
      normals += normal.elements

      # uv
      uvs << i.to_f / tubular_segments.to_f
      uvs << j.to_f / radial_segments.to_f
    end
  end

  # generate indices

  for j in 1..tubular_segments do
    for i in 1..radial_segments do
      # indices
      a = (radial_segments + 1) * (j - 1) + (i - 1)
      b = (radial_segments + 1) * j + (i - 1)
      c = (radial_segments + 1) * j + i
      d = (radial_segments + 1) * (j - 1) + i

      # faces
      indices += [a, b, d]
      indices += [b, c, d]
    end
  end

  # build geometry

  self[:index]    = BufferAttribute.new(indices, 1)
  self[:position] = BufferAttribute.new(vertices, 3)
  self[:normal]   = BufferAttribute.new(normals, 3)
  self[:uv]       = BufferAttribute.new(uvs, 2)
end