Module: Stagecraft::Geometries

Defined in:
lib/stagecraft/geometries.rb

Class Method Summary collapse

Class Method Details

.box(width = 1.0, height = 1.0, depth = 1.0, **dimensions) ⇒ Object



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
# File 'lib/stagecraft/geometries.rb', line 7

def box(width = 1.0, height = 1.0, depth = 1.0, **dimensions)
  width = dimensions.delete(:width) || width
  height = dimensions.delete(:height) || height
  depth = dimensions.delete(:depth) || depth
  reject_unknown_options!(dimensions)
  half = [width, height, depth].map { |value| Float(value) / 2.0 }
  faces = [
    [[1, 0, 0], [[half[0], -half[1], half[2]], [half[0], -half[1], -half[2]], [half[0], half[1], -half[2]], [half[0], half[1], half[2]]]],
    [[-1, 0, 0], [[-half[0], -half[1], -half[2]], [-half[0], -half[1], half[2]], [-half[0], half[1], half[2]], [-half[0], half[1], -half[2]]]],
    [[0, 1, 0], [[-half[0], half[1], half[2]], [half[0], half[1], half[2]], [half[0], half[1], -half[2]], [-half[0], half[1], -half[2]]]],
    [[0, -1, 0], [[-half[0], -half[1], -half[2]], [half[0], -half[1], -half[2]], [half[0], -half[1], half[2]], [-half[0], -half[1], half[2]]]],
    [[0, 0, 1], [[-half[0], -half[1], half[2]], [half[0], -half[1], half[2]], [half[0], half[1], half[2]], [-half[0], half[1], half[2]]]],
    [[0, 0, -1], [[half[0], -half[1], -half[2]], [-half[0], -half[1], -half[2]], [-half[0], half[1], -half[2]], [half[0], half[1], -half[2]]]]
  ]
  positions = []
  normals = []
  uvs = []
  indices = []
  faces.each_with_index do |(normal, vertices), face_index|
    positions.concat(vertices.flatten)
    normals.concat(normal * 4)
    uvs.concat([0, 0, 1, 0, 1, 1, 0, 1])
    base = face_index * 4
    indices.concat([base, base + 1, base + 2, base, base + 2, base + 3])
  end
  build(positions, normals, uvs, indices)
end

.cylinder(radius_top = 1.0, radius_bottom = 1.0, height = 1.0, radial_segments: 32, height_segments: 1, open_ended: false, **dimensions) ⇒ Object



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
# File 'lib/stagecraft/geometries.rb', line 67

def cylinder(radius_top = 1.0, radius_bottom = 1.0, height = 1.0,
             radial_segments: 32, height_segments: 1, open_ended: false, **dimensions)
  radius_top = dimensions.delete(:radius_top) || radius_top
  radius_bottom = dimensions.delete(:radius_bottom) || radius_bottom
  height = dimensions.delete(:height) || height
  reject_unknown_options!(dimensions)
  radial = [Integer(radial_segments), 3].max
  vertical = [Integer(height_segments), 1].max
  slope = (radius_bottom - radius_top) / height.to_f
  side = grid(
    u_segments: radial,
    v_segments: vertical,
    point: lambda { |u, v|
      theta = u * Math::PI * 2.0
      radius = radius_top + ((radius_bottom - radius_top) * v)
      [radius * Math.sin(theta), (0.5 - v) * height, radius * Math.cos(theta)]
    },
    normal: lambda { |u, _v|
      theta = u * Math::PI * 2.0
      Larb::Vec3.new(Math.sin(theta), slope, Math.cos(theta)).normalize.to_a
    }
  )
  return side if open_ended

  caps = []
  caps << disc(radius_top, height / 2.0, radial, up: true) unless radius_top.to_f.zero?
  caps << disc(radius_bottom, -height / 2.0, radial, up: false) unless radius_bottom.to_f.zero?
  merge_geometries(side, *caps)
end

.plane(width = 1.0, height = 1.0, width_segments: 1, height_segments: 1, **dimensions) ⇒ Object



35
36
37
38
39
40
41
42
43
44
# File 'lib/stagecraft/geometries.rb', line 35

def plane(width = 1.0, height = 1.0, width_segments: 1, height_segments: 1, **dimensions)
  width = dimensions.delete(:width) || width
  height = dimensions.delete(:height) || height
  reject_unknown_options!(dimensions)
  grid(
    u_segments: width_segments, v_segments: height_segments,
    point: ->(u, v) { [(u - 0.5) * width, (0.5 - v) * height, 0.0] },
    normal: ->(_u, _v) { [0.0, 0.0, 1.0] }
  )
end

.sphere(radius = 1.0, width_segments: 32, height_segments: 16, **dimensions) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/stagecraft/geometries.rb', line 46

def sphere(radius = 1.0, width_segments: 32, height_segments: 16, **dimensions)
  radius = dimensions.delete(:radius) || radius
  reject_unknown_options!(dimensions)
  radius = Float(radius)
  grid(
    u_segments: [Integer(width_segments), 3].max,
    v_segments: [Integer(height_segments), 2].max,
    point: lambda { |u, v|
      phi = u * Math::PI * 2.0
      theta = v * Math::PI
      [-(radius * Math.cos(phi) * Math.sin(theta)), radius * Math.cos(theta),
       radius * Math.sin(phi) * Math.sin(theta)]
    },
    normal: lambda { |u, v|
      phi = u * Math::PI * 2.0
      theta = v * Math::PI
      [-Math.cos(phi) * Math.sin(theta), Math.cos(theta), Math.sin(phi) * Math.sin(theta)]
    }
  )
end

.torus(radius = 1.0, tube = 0.4, radial_segments: 12, tubular_segments: 48, arc: Math::PI * 2.0, **dimensions) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/stagecraft/geometries.rb', line 97

def torus(radius = 1.0, tube = 0.4, radial_segments: 12, tubular_segments: 48,
          arc: Math::PI * 2.0, **dimensions)
  radius = dimensions.delete(:radius) || radius
  tube = dimensions.delete(:tube) || tube
  reject_unknown_options!(dimensions)
  grid(
    u_segments: [Integer(tubular_segments), 3].max,
    v_segments: [Integer(radial_segments), 3].max,
    point: lambda { |u, v|
      angle = u * arc
      radial_angle = v * Math::PI * 2.0
      distance = radius + (tube * Math.cos(radial_angle))
      [distance * Math.cos(angle), distance * Math.sin(angle), tube * Math.sin(radial_angle)]
    },
    normal: lambda { |u, v|
      angle = u * arc
      radial_angle = v * Math::PI * 2.0
      [Math.cos(angle) * Math.cos(radial_angle), Math.sin(angle) * Math.cos(radial_angle),
       Math.sin(radial_angle)]
    }
  )
end