class Mittsu::STLLoader

Constants

FLOAT
NORMAL_PATTERN
VERTEX_PATTERN

Public Class Methods

new(manager = DefaultLoadingManager) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 11
def initialize(manager = DefaultLoadingManager)
  @manager = manager
  @_listeners = {}
end

Public Instance Methods

load(url) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 16
def load(url)
  loader = FileLoader.new(@manager)

  data = loader.load(url)
  parse(data)
end
parse(data) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 23
def parse(data)
  reset_loader_vars
  stream = StringIO.new(data, "rb")
  # Load STL header (first 80 bytes max)
  header = stream.read(80)
  if header.slice(0,5) === "solid"
    stream.rewind
    parse_ascii(stream)
  else
    parse_binary(stream)
  end
  @group
end

Private Instance Methods

add_mesh(vertices, faces) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 157
def add_mesh(vertices, faces)
  geometry = Geometry.new
  geometry.vertices = vertices
  geometry.faces = faces
  geometry.compute_bounding_sphere
  @group.add Mesh.new(geometry)
end
face_with_merged_vertices(vertices) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 125
def face_with_merged_vertices(vertices)
  new_vertices = []
  indices = []
  vertices.each do |v|
    index, is_new = vertex_index(v)
    indices << index
    if is_new
      new_vertices << v
      @vertex_count += 1
    end
  end
  # Return face and new vertex list
  return Face3.new(
    indices[0],
    indices[1],
    indices[2]
  ), new_vertices
end
parse_ascii(stream) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 46
def parse_ascii(stream)
  while line = read_line(stream)
    case line
    when /^\s*solid/
      parse_ascii_solid(stream)
    else
      raise_error
    end
  end
end
parse_ascii_facet(line, stream) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 75
def parse_ascii_facet(line, stream)
  vertices = []
  normal = nil
  if line.match NORMAL_PATTERN
    normal = Vector3.new($1, $2, $3)
  end
  while line = read_line(stream)
    case line
    when /^\s*outer loop/
      nil # Ignored
    when /^\s*endloop/
      nil # Ignored
    when VERTEX_PATTERN
      vertices << Vector3.new($1, $2, $3)
    when /^\s*endfacet/
      break
    else
      raise_error
    end
  end
  return nil if vertices.length != 3
  # Merge with existing vertices
  face, new_vertices = face_with_merged_vertices(vertices)
  face.normal = normal
  return new_vertices, face
end
parse_ascii_solid(stream) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 57
def parse_ascii_solid(stream)
  vertices = []
  faces = []
  while line = read_line(stream)
    case line
    when /^\s*facet/
      facet_vertices, face = parse_ascii_facet(line, stream)
      vertices += facet_vertices
      faces << face
    when /^\s*endsolid/
      break
    else
      raise_error
    end
  end
  add_mesh vertices, faces
end
parse_binary(stream) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 102
def parse_binary(stream)
  vertices = []
  faces = []
  num_faces = stream.read(4).unpack('L<').first
  num_faces.times do |i|
    # Face normal
    normal = read_binary_vector(stream)
    # Vertices
    face_vertices = []
    face_vertices << read_binary_vector(stream)
    face_vertices << read_binary_vector(stream)
    face_vertices << read_binary_vector(stream)
    # Throw away the attribute bytes
    stream.read(2)
    # Store data
    face, new_vertices = face_with_merged_vertices(face_vertices)
    face.normal = normal
    faces << face
    vertices += new_vertices
  end
  add_mesh vertices, faces
end
raise_error() click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 182
def raise_error
  raise "Mittsu::STLLoader: Unhandled line #{@line_num}"
end
read_binary_vector(stream) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 165
def read_binary_vector(stream)
  Vector3.new(
    read_le_float(stream),
    read_le_float(stream),
    read_le_float(stream)
  )
end
read_le_float(stream) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 173
def read_le_float(stream)
  stream.read(4).unpack('e').first
end
read_line(stream) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 177
def read_line(stream)
  @line_num += 1
  stream.gets
end
reset_loader_vars() click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 39
def reset_loader_vars
  @vertex_hash = {}
  @vertex_count = 0
  @line_num = 0
  @group = Group.new
end
vertex_index(vertex) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 144
def vertex_index(vertex)
  key = vertex_key(vertex)
  if i = @vertex_hash[key]
    return i, false
  else
    return (@vertex_hash[key] = @vertex_count), true
  end
end
vertex_key(vertex) click to toggle source
# File lib/mittsu/loaders/stl_loader.rb, line 153
def vertex_key(vertex)
  vertex.elements.pack("D*")
end