class Blender3d::Model

Attributes

blocks[R]
codes[R]
header[R]
pointers[R]

Public Class Methods

from_file(path) click to toggle source
# File lib/blender-3d/model.rb, line 5
def self.from_file(path)
  File.open(path, 'rb') { |file| new(file) }
end
new(file = nil) click to toggle source
# File lib/blender-3d/model.rb, line 9
def initialize(file = nil)
  @blocks = []
  deserialize(file) if file
end

Public Instance Methods

create_reader(file) click to toggle source
# File lib/blender-3d/model.rb, line 48
def create_reader(file)
  ObjectReader.new(file, self)
end
deserialize(file) click to toggle source
# File lib/blender-3d/model.rb, line 14
def deserialize(file)
  @header = FileHeader.new(file)
  reader = create_reader(file)
  @blocks.clear

  loop do
    @blocks << FileBlock.new(reader)
    break if reader.tell == reader.file.size
  end

  @pointers = @blocks.reject { |block| block.code == 'ENDB' }.map { |block| [block.pointer, block] }.to_h

  dna_block = self.dna_block
  return self unless dna_block

  render_block = @blocks.find { |b| b.code == 'REND' }
  if render_block
    render_block.type_index = dna_block.data.structures.size
    dna_block.data.structures << render_info
  end

  @blocks.select { |block| block.type_index != 0 }.each do |block|
    block.type = dna_block.data.structures[block.type_index]
  end

  @blocks.select(&:type).each_with_index do |block, i|
    block.parse_data(self)
  end

  @codes = @blocks.group_by(&:code).sort.to_h

  self
end
dna_block() click to toggle source
# File lib/blender-3d/model.rb, line 52
def dna_block
  @blocks.find { |block| block.code == 'DNA1' }
end
render_info() click to toggle source
# File lib/blender-3d/model.rb, line 56
def render_info
  @render_info ||= begin
    sizeof_int = dna_block.data.types.find { |name, _| name == 'int' }.last
    struct_size = 2 * sizeof_int + 64
    StructureDefinition.new('RenderInfo', struct_size, [
      Field.new(SimpleType.new('int'), 'sfra'),
      Field.new(SimpleType.new('int'), 'efra'),
      Field.new(FixedLengthStringType.new(64), 'scene_name'),
    ])
  end
end
to_xml() click to toggle source
# File lib/blender-3d/model.rb, line 68
def to_xml
  content = blocks.reject { |b| b.code == 'DNA1' }.map(&:to_xml)
  REXML::Element.new(self.class.basename).tap do |e|
    e.add_attribute 'identifier', @header.identifier
    e.add_attribute 'pointer_size', @header.pointer_size.to_s
    e.add_attribute 'endianness', @header.endianness.to_s
    e.add_attribute 'version', @header.version
    content.each_with_index do |c, i|
      c.add_attribute 'index', i.to_s
      e << c
    end
  end
end