class Mittsu::CylinderGeometry

Public Class Methods

new(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)) click to toggle source
Calls superclass method Mittsu::Geometry::new
# File lib/mittsu/extras/geometries/cylinder_geometry.rb, line 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))
  super()

  @type = 'CylinderGeometry'

  @parameters = {
    radius_top:      radius_top,
    radius_bottom:   radius_bottom,
    height:          height,
    radial_segments: radial_segments,
    height_segments: height_segments,
    open_ended:      open_ended,
    theta_start:     theta_start,
    theta_length:    theta_length
  }

  height_half = height / 2.0

  index_rows = []
  uv_rows = []

  for y in 0..height_segments do
    index_row = []
    uv_row = []

    v = y.to_f / height_segments.to_f
    radius = v * (radius_bottom - radius_top) + radius_top

    for x in 0..radial_segments do
      u = x.to_f / radial_segments

      vertex = Vector3.new
      vertex.x = radius * ::Math.sin(u * theta_length + theta_start)
      vertex.y = -v * height + height_half
      vertex.z = radius * ::Math.cos(u * theta_length + theta_start)

      @vertices << vertex

      index_row << (vertices.length - 1)
      uv_row << Vector2.new(u, 1.0 - v)
    end

    index_rows << index_row
    uv_rows << uv_row
  end

  tan_theta = (radius_bottom - radius_top) / height

  na = nil
  nb = nil

  for x in 0...radial_segments do
    if radius_top != 0
      na = @vertices[index_rows[0][x]].clone
      nb = @vertices[index_rows[0][x + 1]].clone
    else
      na = @vertices[index_rows[1][x]].clone
      nb = @vertices[index_rows[1][x + 1]].clone
    end

    na.y = ::Math.sqrt(na.x * na.x + na.z * na.z) * tan_theta
    na.normalize

    nb.y = ::Math.sqrt(nb.x * nb.x + nb.z * nb.z) * tan_theta
    nb.normalize

    for y in 0...height_segments do
      v1 = index_rows[y][x]
      v2 = index_rows[y + 1][x]
      v3 = index_rows[y + 1][x + 1]
      v4 = index_rows[y][x + 1]

      n1 = na.clone
      n2 = na.clone
      n3 = nb.clone
      n4 = nb.clone

      uv1 = uv_rows[y][x].clone
      uv2 = uv_rows[y + 1][x].clone
      uv3 = uv_rows[y + 1][x + 1].clone
      uv4 = uv_rows[y][x + 1].clone

      @faces << Face3.new(v1, v2, v4, [n1, n2, n4])
      @face_vertex_uvs[0] << [uv1, uv2, uv4]

      @faces << Face3.new(v2, v3, v4, [n2.clone, n3, n4.clone])
      @face_vertex_uvs[0] << [uv2.clone, uv3, uv4.clone]
    end
  end

  # top cap

  if !open_ended && radius_top > 0.0
    @vertices << Vector3.new(0, height_half, 0)

    for x in 0...radial_segments do
      v1 = index_rows[0][x]
      v2 = index_rows[0][x + 1]
      v3 = @vertices.length - 1

      n1 = Vector3.new(0, 1, 0)
      n2 = Vector3.new(0, 1, 0)
      n3 = Vector3.new(0, 1, 0)

      uv1 = uv_rows[0][x].clone
      uv2 = uv_rows[0][x + 1].clone
      uv3 = Vector2.new(uv2.x, 0)

      @faces << Face3.new(v1, v2, v3, [n1, n2, n3])
      @face_vertex_uvs[0] << [uv1, uv2, uv3]
    end
  end

  # bottom cap

  if !open_ended && radius_bottom > 0.0
    @vertices << Vector3.new(0, -height_half, 0)

    for x in 0...radial_segments do
      v1 = index_rows[height_segments][x + 1]
      v2 = index_rows[height_segments][x]
      v3 = @vertices.length - 1

      n1 = Vector3.new(0, -1, 0)
      n2 = Vector3.new(0, -1, 0)
      n3 = Vector3.new(0, -1, 0)

      uv1 = uv_rows[height_segments][x].clone
      uv2 = uv_rows[height_segments][x + 1].clone
      uv3 = Vector2.new(uv2.x, 0)

      @faces << Face3.new(v1, v2, v3, [n1, n2, n3])
      @face_vertex_uvs[0] << [uv1, uv2, uv3]
    end
  end

  compute_face_normals
end