Class: CyberarmEngine::ColladaParser

Inherits:
Model::Parser show all
Defined in:
lib/cyberarm_engine/model/parsers/collada_parser.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Model::Parser

#add_material, #change_object, #current_material, find, inherited, #initialize, #set_material, #set_object, supported_formats

Constructor Details

This class inherits a constructor from CyberarmEngine::Model::Parser

Class Method Details

.handlesObject



3
4
5
# File 'lib/cyberarm_engine/model/parsers/collada_parser.rb', line 3

def self.handles
  [:dae]
end

Instance Method Details

#build_faces(_id, mesh) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/cyberarm_engine/model/parsers/collada_parser.rb', line 100

def build_faces(_id, mesh)
  material_name = mesh.at_css("triangles").attributes["material"].value
  set_material(material_name)

  positions_index = []
  normals_index = []
  uvs_index = []

  mesh.at_css("triangles p").children.first.to_s.split(" ").map { |i| Integer(i) }.each_slice(3).each do |slice|
    positions_index << slice[0]
    normals_index << slice[1]
    uvs_index << slice[2]
  end

  norm_index = 0
  positions_index.each_slice(3) do |slice|
    face = Face.new
    face.vertices = []
    face.uvs      = []
    face.normals  = []
    face.colors   = []
    face.material = current_material
    face.smoothing = @model.smoothing

    slice.each do |index|
      face.vertices << @model.vertices[index]
      # face.uvs << @model.uvs[index]
      face.normals << @model.normals[normals_index[norm_index]]
      face.colors << current_material.diffuse

      norm_index += 1
    end

    @model.current_object.faces << face
    @model.faces << face
  end
end

#get_normals(id, mesh) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
# File 'lib/cyberarm_engine/model/parsers/collada_parser.rb', line 67

def get_normals(id, mesh)
  normals = mesh.at_css("[id=\"#{id}-normals\"]")
  array = normals.at_css("[id=\"#{id}-normals-array\"]")

  stride = Integer(normals.at_css("[source=\"##{id}-normals-array\"]").attributes["stride"].value)
  list = array.children.first.to_s.split(" ").map { |f| Float(f) }.each_slice(stride).each do |slice|
    normal = Vector.new(*slice)
    @model.current_object.normals << normal
    @model.normals << normal
  end
end

#get_positions(id, mesh) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
# File 'lib/cyberarm_engine/model/parsers/collada_parser.rb', line 55

def get_positions(id, mesh)
  positions = mesh.at_css("[id=\"#{id}-positions\"]")
  array = positions.at_css("[id=\"#{id}-positions-array\"]")

  stride = Integer(positions.at_css("[source=\"##{id}-positions-array\"]").attributes["stride"].value)
  list = array.children.first.to_s.split(" ").map { |f| Float(f) }.each_slice(stride).each do |slice|
    position = Vector.new(*slice)
    @model.current_object.vertices << position
    @model.vertices << position
  end
end

#get_texture_coordinates(id, mesh) ⇒ Object



79
80
# File 'lib/cyberarm_engine/model/parsers/collada_parser.rb', line 79

def get_texture_coordinates(id, mesh)
end

#parseObject



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/cyberarm_engine/model/parsers/collada_parser.rb', line 7

def parse
  @collada = Nokogiri::XML(File.read(@model.file_path))

  @collada.css("library_materials material").each do |material|
    parse_material(material)
  end

  @collada.css("library_geometries geometry").each do |geometry|
    parse_geometry(geometry)
  end

  @model.calculate_bounding_box(@model.vertices, @model.bounding_box)
  @model.objects.each do |o|
    @model.calculate_bounding_box(o.vertices, o.bounding_box)
  end
end

#parse_geometry(geometry) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/cyberarm_engine/model/parsers/collada_parser.rb', line 39

def parse_geometry(geometry)
  geometry_id = geometry.attributes["id"].value
  geometry_name = geometry.attributes["name"].value

  change_object(geometry_id, geometry_name)

  mesh = geometry.at_css("mesh")

  get_positions(geometry_id, mesh)
  get_normals(geometry_id, mesh)
  get_texture_coordinates(geometry_id, mesh)

  project_node(geometry_name)
  build_faces(geometry_id, mesh)
end

#parse_material(material) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/cyberarm_engine/model/parsers/collada_parser.rb', line 24

def parse_material(material)
  name = material.attributes["id"].value
  effect_id = material.at_css("instance_effect").attributes["url"].value

  mat = Model::Material.new(name)
  effect = @collada.at_css("[id=\"#{effect_id.sub('#', '')}\"]")

  emission = effect.at_css("emission color")
  diffuse = effect.at_css("diffuse color").children.first.to_s.split(" ").map { |c| Float(c) }

  mat.diffuse = Color.new(*diffuse[0..2])

  add_material(name, mat)
end

#project_node(name) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/cyberarm_engine/model/parsers/collada_parser.rb', line 82

def project_node(name)
  @collada.css("library_visual_scenes visual_scene node").each do |node|
    next unless node.attributes["name"].value == name

    transform = Transform.new(node.at_css("matrix").children.first.to_s.split(" ").map { |f| Float(f) })

    @model.current_object.vertices.each do |vert|
      v = vert.multiply_transform(transform)
      vert.x = v.x
      vert.y = v.y
      vert.z = v.z
      vert.w = v.w
    end

    break
  end
end