From dbf4edbb93712f659db07b47bdbc22c07c853adc Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Thu, 30 Jan 2020 13:36:34 -0600 Subject: [PATCH] Collada parser mostly works for single object/material models --- lib/model/model_object.rb | 5 +++-- lib/model/parser.rb | 22 ++++++++++++++++++++-- lib/model/parsers/collada_parser.rb | 18 +++++++++++++++--- lib/model/parsers/wavefront_parser.rb | 2 +- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/lib/model/model_object.rb b/lib/model/model_object.rb index 22f6d77..18e3be9 100644 --- a/lib/model/model_object.rb +++ b/lib/model/model_object.rb @@ -1,10 +1,11 @@ class IMICFPS class Model class ModelObject - attr_reader :name, :vertices, :textures, :normals, :bounding_box, :debug_color + attr_reader :id, :name, :vertices, :textures, :normals, :bounding_box, :debug_color attr_accessor :faces, :scale - def initialize(name) + def initialize(id, name) + @id = id @name = name @vertices = [] @textures = [] diff --git a/lib/model/parser.rb b/lib/model/parser.rb index f9da6f6..6f03071 100644 --- a/lib/model/parser.rb +++ b/lib/model/parser.rb @@ -30,8 +30,26 @@ class IMICFPS def parse end - def change_object(name) - @model.objects << Model::ModelObject.new(name) + def set_object(id: nil, name: nil) + _model = nil + + if id + _model = @model.objects.find { |o| o.id == id } + elsif name + _model = @model.objects.find { |o| o.id == id } + else + raise "Must provide either an id: or name:" + end + + if _model + @model.current_object = _model + else + raise "Couldn't find ModelObject!" + end + end + + def change_object(id, name) + @model.objects << Model::ModelObject.new(id, name) @model.current_object = @model.objects.last end diff --git a/lib/model/parsers/collada_parser.rb b/lib/model/parsers/collada_parser.rb index 44dc14d..28525fe 100644 --- a/lib/model/parsers/collada_parser.rb +++ b/lib/model/parsers/collada_parser.rb @@ -40,7 +40,7 @@ class IMICFPS geometry_id = geometry.attributes["id"].value geometry_name = geometry.attributes["name"].value - change_object(geometry_name) + change_object(geometry_id, geometry_name) mesh = geometry.at_css("mesh") @@ -80,10 +80,20 @@ class IMICFPS 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| - set_material(material_name) + 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 = [] @@ -95,8 +105,10 @@ class IMICFPS slice.each do |index| face.vertices << @model.vertices[index] # face.uvs << @model.uvs[index] - face.normals << @model.normals[index] + face.normals << @model.normals[normals_index[norm_index]] face.colors << current_material.diffuse + + norm_index += 1 end @model.current_object.faces << face diff --git a/lib/model/parsers/wavefront_parser.rb b/lib/model/parsers/wavefront_parser.rb index c4566e5..356b47e 100644 --- a/lib/model/parsers/wavefront_parser.rb +++ b/lib/model/parsers/wavefront_parser.rb @@ -23,7 +23,7 @@ class IMICFPS when 'usemtl' set_material(array[1]) when 'o' - change_object(array[1]) + change_object(nil, array[1]) when 's' set_smoothing(array[1]) when 'v'