Added evergreen_tree model, added work-in-progress collada parser, renamed ModelLoader to ModelCache

This commit is contained in:
2020-01-30 11:25:31 -06:00
parent 31f0fa141b
commit 8b35bf037e
13 changed files with 529 additions and 41 deletions

View File

@@ -57,9 +57,9 @@ class IMICFPS
end
def bind_model
model = ModelLoader.new(manifest: @manifest, entity: @dummy_entity)
model = ModelCache.new(manifest: @manifest, entity: @dummy_entity)
raise "model isn't a model!" unless model.is_a?(ModelLoader)
raise "model isn't a model!" unless model.is_a?(ModelCache)
@bound_model = model
@bound_model.model.entity = self
@bounding_box = normalize_bounding_box_with_offset

View File

@@ -33,7 +33,14 @@ class IMICFPS
@bounding_box = BoundingBox.new
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
parse( Model::Parser.find(File.basename(file_path).split(".").last.to_sym) )
type = File.basename(file_path).split(".").last.to_sym
parser = Model::Parser.find(type)
unless parser
raise "Unsupported model type '.#{type}', supported models are: #{Model::Parser.supported_formats}"
end
parse(parser)
puts "#{@file_path.split('/').last} took #{((Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)-start_time)/1000.0).round(2)} seconds to parse" if window.config.get(:debug_options, :stats)
@@ -131,7 +138,7 @@ class IMICFPS
@faces.each do |face|
pos << face.vertices.map { |vert| [vert.x, vert.y, vert.z] }
colors << face.colors.map { |vert| [vert.x, vert.y, vert.z] }
colors << face.colors.map { |color| [color.red, color.green, color.blue] }
norms << face.normals.map { |vert| [vert.x, vert.y, vert.z, vert.weight] }
if has_texture?

View File

@@ -19,12 +19,33 @@ class IMICFPS
return found_parser
end
def self.supported_formats
@@parsers.map { |parser| parser.handles }.flatten.map { |s| ".#{s}" }.join(", ")
end
def initialize(model)
@model = model
end
def parse
end
def change_object(name)
@model.objects << Model::ModelObject.new(name)
@model.current_object = @model.objects.last
end
def set_material(name)
@model.current_material = name
end
def add_material(name, material)
@model.materials[name] = material
end
def current_material
@model.materials[@model.current_material]
end
end
end
end

View File

@@ -0,0 +1,107 @@
class IMICFPS
class ColladaParser < Model::Parser
def self.handles
[:dae]
end
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
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
def parse_geometry(geometry)
geometry_id = geometry.attributes["id"].value
geometry_name = geometry.attributes["name"].value
change_object(geometry_name)
mesh = geometry.at_css("mesh")
get_positions(geometry_id, mesh)
get_normals(geometry_id, mesh)
get_texture_coordinates(geometry_id, mesh)
build_faces(geometry_id, mesh)
end
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
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
def get_texture_coordinates(id, mesh)
end
def build_faces(id, mesh)
material_name = mesh.at_css("triangles").attributes["material"].value
mesh.at_css("triangles p").children.first.to_s.split(" ").map { |i| Integer(i) }.each_slice(3).each do |slice|
set_material(material_name)
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[index]
face.colors << current_material.diffuse
end
@model.current_object.faces << face
@model.faces << face
end
end
end
end

View File

@@ -49,11 +49,11 @@ class IMICFPS
face.uvs = []
face.normals = []
face.colors = []
face.material = material
face.material = current_material
face.smoothing= @model.smoothing
mat = face.material.diffuse
color = Vector.new(mat.red, mat.green, mat.blue)
color = mat
verts.each_with_index do |v, index|
@@ -110,11 +110,6 @@ class IMICFPS
end
end
def change_object(name)
@model.objects << Model::ModelObject.new(name)
@model.current_object = @model.objects.last
end
def set_smoothing(value)
if value == "1"
@model.smoothing = true
@@ -123,20 +118,6 @@ class IMICFPS
end
end
def set_material(name)
@model.current_material = name
end
def material
@model.materials[@model.current_material]
end
def faces_count
count = 0
@model.objects.each {|o| count+=o.faces.count}
return count
end
def add_vertex(array)
@model.vertex_count+=1
vert = nil

View File

@@ -1,9 +1,5 @@
class IMICFPS
class ModelLoader
def self.supported_models
["Wavefront OBJ"]
end
class ModelCache
CACHE = {}
attr_reader :model, :name, :debug_color
@@ -16,20 +12,13 @@ class IMICFPS
@debug_color = Color.new(0.0, 1.0, 0.0)
@model = nil
@supported_models = ["OBJ"]
unless load_model_from_cache
case @type
when :obj
@model = IMICFPS::Model.new(file_path: @model_file)
else
raise "Unsupported model type, supported models are: #{@supported_models.join(', ')}"
end
@model = IMICFPS::Model.new(file_path: @model_file)
cache_model
end
return self
end

View File

@@ -53,7 +53,7 @@ class IMICFPS
hash = @assets[@asset_index]
case hash[:type]
when :model
ModelLoader.new(manifest: hash[:manifest], entity: @dummy_entity)
ModelCache.new(manifest: hash[:manifest], entity: @dummy_entity)
when :shader
if window.config.get(:debug_options, :use_shaders)
shader = Shader.new(name: hash[:name], includes_dir: "shaders/include", vertex: "shaders/vertex/#{hash[:name]}.glsl", fragment: "shaders/fragment/#{hash[:name]}.glsl")