diff --git a/Gemfile b/Gemfile index d03df08..7e9925f 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,7 @@ source "https://rubygems.org" gem "opengl-bindings", require: "opengl" gem "cyberarm_engine", git: "https://github.com/cyberarm/cyberarm_engine" +gem "nokogiri" group(:packaging) do gem "ocra" diff --git a/assets/base/evergreen_tree/manifest.yaml b/assets/base/evergreen_tree/manifest.yaml new file mode 100644 index 0000000..3c7f5d5 --- /dev/null +++ b/assets/base/evergreen_tree/manifest.yaml @@ -0,0 +1,4 @@ +--- +name: "evergreen_tree" +model: "evergreen_tree.dae" +collision: "boundingbox" \ No newline at end of file diff --git a/assets/base/evergreen_tree/model/evergreen_tree.dae b/assets/base/evergreen_tree/model/evergreen_tree.dae new file mode 100644 index 0000000..358efcc --- /dev/null +++ b/assets/base/evergreen_tree/model/evergreen_tree.dae @@ -0,0 +1,376 @@ + + + + + Blender User + Blender 2.81.16 commit date:2019-12-04, commit time:11:32, hash:f1aa4d18d49d + + 2020-01-30T08:56:21 + 2020-01-30T08:56:21 + + Z_UP + + + + + + + 39.59775 + 1.777778 + 0.1 + 100 + + + + + + 0 + 0 + 10 + + + + + + + + + 1000 1000 1000 + 1 + 0 + 0.00111109 + + + + + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 1000 + 29.99998 + 75 + 0.15 + 0 + 1 + 2 + 0.04999995 + 30.002 + 1 + 3 + 2880 + 3 + 1 + 1 + 0.1 + 0.1 + 1 + + + + + + + + + + + 0 0 0 1 + + + 0 0.4868966 0.07537682 1 + + + 1.45 + + + + + + + + + + + 0 0 0 1 + + + 0 0.5173332 0.03164556 1 + + + 1.45 + + + + + + + + + + + 0 0 0 1 + + + 0.3031975 0.1076129 0.05296437 1 + + + 1.45 + + + + + + + + + + + + + + + + + + + + + + + -0.7701593 -0.7701593 0 0.7701593 -0.7701593 0 -0.7701593 0.7701593 0 0.7701593 0.7701593 0 0 0 0.6063125 + + + + + + + + + + 0 0 -1 0 -0.6185703 0.7857296 0.6185703 0 0.7857295 -0.6185703 0 0.7857295 0 0.6185703 0.7857296 + + + + + + + + + + 0 1 1 0 0 0 0 0 1 0 0 0 1 0 1 1 1 0 0 1 0 0 0 1 1 1 0 1 1 1 0 1 1 1 1 0 + + + + + + + + + + + + + + +

2 0 0 1 0 1 0 0 2 0 1 3 1 1 4 4 1 5 1 2 6 3 2 7 4 2 8 2 3 9 0 3 10 4 3 11 3 4 12 2 4 13 4 4 14 2 0 15 3 0 16 1 0 17

+
+
+
+ + + + -1 -1 0 1 -1 0 -1 1 0 1 1 0 -0.4597772 -0.4597772 0.5360521 0.4597772 -0.4597772 0.5360521 -0.4597772 0.4597772 0.5360521 0.4597772 0.4597772 0.5360521 + + + + + + + + + + 0 0 -1 0 0 1 0 -0.7043614 0.7098416 0.7043614 0 0.7098416 -0.7043614 0 0.7098416 0 0.7043614 0.7098416 0 -0.7043614 0.7098415 0.7043614 0 0.7098416 -0.7043614 0 0.7098416 0 0.7043614 0.7098415 + + + + + + + + + + 0 1 1 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 1 0 0 0 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 1 0 1 1 0 1 1 0 1 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1 0 1 0 1 1 1 + + + + + + + + + + + + + + +

2 0 0 1 0 1 0 0 2 5 1 3 6 1 4 4 1 5 1 2 6 4 2 7 0 2 8 3 3 9 5 3 10 1 3 11 0 4 12 6 4 13 2 4 14 2 5 15 7 5 16 3 5 17 2 0 18 3 0 19 1 0 20 5 1 21 7 1 22 6 1 23 1 6 24 5 6 25 4 6 26 3 7 27 7 7 28 5 7 29 0 8 30 4 8 31 6 8 32 2 9 33 6 9 34 7 9 35

+
+
+
+ + + + -1.366034 -1.366034 0 1.366034 -1.366034 0 -1.366034 1.366034 0 1.366034 1.366034 0 -0.7 -0.7 0.5 0.7 -0.7 0.5 -0.7 0.7 0.5 0.7 0.7 0.5 + + + + + + + + + + 0 0 -1 0 0 1 0 -0.6003649 0.7997263 0.6003648 0 0.7997263 -0.6003648 0 0.7997263 0 0.6003649 0.7997263 0 -0.6003648 0.7997263 0.6003648 0 0.7997263 -0.6003648 0 0.7997263 0 0.6003648 0.7997263 + + + + + + + + + + 0 1 1 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 1 0 0 0 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 1 0 1 1 0 1 1 0 1 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1 0 1 0 1 1 1 + + + + + + + + + + + + + + +

2 0 0 1 0 1 0 0 2 5 1 3 6 1 4 4 1 5 1 2 6 4 2 7 0 2 8 3 3 9 5 3 10 1 3 11 0 4 12 6 4 13 2 4 14 2 5 15 7 5 16 3 5 17 2 0 18 3 0 19 1 0 20 5 1 21 7 1 22 6 1 23 1 6 24 5 6 25 4 6 26 3 7 27 7 7 28 5 7 29 0 8 30 4 8 31 6 8 32 2 9 33 6 9 34 7 9 35

+
+
+
+ + + + 0 0.5 0 -0.4755282 0.1545085 0 -0.2938926 -0.4045085 0 0.2938927 -0.4045085 0 0.4755282 0.1545085 0 0 0.4 2 -0.3804226 0.1236068 2 -0.235114 -0.3236068 2 0.2351141 -0.3236068 2 0.3804226 0.1236068 2 3.64108e-7 0.42 4.3 -0.3043377 0.1988854 4.3 -0.1880909 -0.1588854 4.3 0.1880916 -0.1588854 4.3 0.3043384 0.1988855 4.3 -8.83978e-7 0.156 6 -0.2434713 -0.0208916 6 -0.1504738 -0.3071084 6 0.1504722 -0.3071084 6 0.2434695 -0.02089154 6 -1.64407e-6 0.02799999 7 -0.1217368 -0.06044578 7 -0.0752381 -0.2035542 7 0.07523488 -0.2035542 7 0.1217336 -0.06044578 7 + + + + + + + + + + 0 0 -1 0.5877706 0.8089972 -0.007034838 -0.587305 0.8083561 0.04041773 0.9502794 -0.3087643 0.04041779 -0.9502794 -0.3087645 0.04041779 0.5873049 0.808356 0.04041779 0 -0.9991829 0.04041779 0.95104 -0.3090115 -0.005896985 0 -0.9974453 0.07143497 -0.5877708 0.808997 -0.007034659 0.9502357 -0.3087501 0.04153919 -0.9502357 -0.3087502 0.04153949 0.5846588 0.8047139 0.1030038 -0.9510399 -0.3090118 -0.005898416 0.5832006 0.8027067 0.124656 0 -0.9962205 -0.08686035 -0.5832004 0.8027069 0.1246552 0 0 1 0 -0.994681 0.1030034 -0.5846592 0.8047137 0.1030029 0.9459978 -0.3073732 0.1030041 -0.945998 -0.3073735 0.1030026 0.5877708 0.808997 -0.007034838 -0.587305 0.808356 0.04041779 0.9502794 -0.3087643 0.04041779 -0.9502794 -0.3087646 0.04041779 0.587305 0.808356 0.04041779 0 -0.9991829 0.04041779 0.9510402 -0.3090113 -0.005896985 0 -0.9974453 0.07143497 -0.5877707 0.808997 -0.007034659 0.9502358 -0.3087501 0.04153919 -0.9502357 -0.3087503 0.04153949 0.5846586 0.804714 0.1030038 -0.9510401 -0.3090116 -0.005898416 0.5832004 0.8027068 0.124656 0 -0.9962205 -0.08686041 -0.5832005 0.802707 0.1246553 -1.10718e-5 0 1 0 -0.994681 0.1030033 -0.5846592 0.8047137 0.1030029 0.9459979 -0.3073732 0.1030041 -0.9459978 -0.3073736 0.1030027 + + + + + + + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + + + + + + + + + + + + +

4 0 0 3 0 1 2 0 2 5 1 3 14 1 4 9 1 5 1 2 6 5 2 7 0 2 8 4 3 9 8 3 10 3 3 11 2 4 12 6 4 13 1 4 14 0 5 15 9 5 16 4 5 17 3 6 18 7 6 19 2 6 20 13 7 21 19 7 22 18 7 23 8 8 24 12 8 25 7 8 26 5 9 27 11 9 28 10 9 29 9 10 30 13 10 31 8 10 32 6 11 33 12 11 34 11 11 35 15 12 36 24 12 37 19 12 38 12 13 39 16 13 40 11 13 41 14 14 42 15 14 43 19 14 44 12 15 45 18 15 46 17 15 47 11 16 48 15 16 49 10 16 50 22 17 51 24 17 52 20 17 53 17 18 54 23 18 55 22 18 56 16 19 57 20 19 58 15 19 59 18 20 60 24 20 61 23 20 62 16 21 63 22 21 64 21 21 65 2 0 66 1 0 67 0 0 68 0 0 69 4 0 70 2 0 71 5 22 72 10 22 73 14 22 74 1 23 75 6 23 76 5 23 77 4 24 78 9 24 79 8 24 80 2 25 81 7 25 82 6 25 83 0 26 84 5 26 85 9 26 86 3 27 87 8 27 88 7 27 89 13 28 90 14 28 91 19 28 92 8 29 93 13 29 94 12 29 95 5 30 96 6 30 97 11 30 98 9 31 99 14 31 100 13 31 101 6 32 102 7 32 103 12 32 104 15 33 105 20 33 106 24 33 107 12 34 108 17 34 109 16 34 110 14 35 111 10 35 112 15 35 113 12 36 114 13 36 115 18 36 116 11 37 117 16 37 118 15 37 119 20 38 120 21 38 121 22 38 122 22 17 123 23 17 124 24 17 125 17 39 126 18 39 127 23 39 128 16 40 129 21 40 130 20 40 131 18 41 132 19 41 133 24 41 134 16 42 135 17 42 136 22 42 137

+
+
+
+
+ + + + 1.326094 0.4826588 0 0 -0.4826588 1.326094 0 0 0 0 3.66912 5.393049 0 0 0 1 + + + + + + + + + + + + 1.544178 0.2722803 0 0 -0.2722803 1.544178 0 0 0 0 4.0768 3.677205 0 0 0 1 + + + + + + + + + + + + 1.6 0 0 0 0 1.6 0 0 0 0 4.16 2 0 0 0 1 + + + + + + + + + + + + 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 + + + + + + + + + + + + 0.6859207 -0.3240135 0.6515582 7.358891 0.7276763 0.3054208 -0.6141704 -6.925791 0 0.8953956 0.4452714 4.958309 0 0 0 1 + + + + -0.2908646 -0.7711008 0.5663932 4.076245 0.9551712 -0.1998834 0.2183912 1.005454 -0.05518906 0.6045247 0.7946723 5.903862 0 0 0 1 + + + + + + + +
\ No newline at end of file diff --git a/blends/evergreen_tree.blend b/blends/evergreen_tree.blend new file mode 100644 index 0000000..06563a7 Binary files /dev/null and b/blends/evergreen_tree.blend differ diff --git a/i-mic-fps.rb b/i-mic-fps.rb index 8d3b31c..0c1f3e1 100644 --- a/i-mic-fps.rb +++ b/i-mic-fps.rb @@ -6,6 +6,7 @@ require "time" require "opengl" require "glu" +require "nokogiri" begin require_relative "../cyberarm_engine/lib/cyberarm_engine" @@ -75,7 +76,6 @@ require_relative "lib/component" require_relative "lib/components/building" require_relative "lib/game_objects/entity" -require_relative "lib/game_objects/model_loader" require_relative "lib/game_objects/light" require_relative "lib/game_objects/camera" @@ -84,11 +84,13 @@ require_relative "lib/game_objects/entities/skydome" require_relative "lib/game_objects/entities/terrain" require_relative "lib/model" +require_relative "lib/model_cache" require_relative "lib/model/parser" require_relative "lib/model/model_object" require_relative "lib/model/material" require_relative "lib/model/parsers/wavefront_parser" +require_relative "lib/model/parsers/collada_parser" require_relative "lib/map_parser" require_relative "lib/manifest" diff --git a/lib/game_objects/entity.rb b/lib/game_objects/entity.rb index a623b22..85ddc39 100644 --- a/lib/game_objects/entity.rb +++ b/lib/game_objects/entity.rb @@ -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 diff --git a/lib/model.rb b/lib/model.rb index 69c8722..a346590 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -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? diff --git a/lib/model/parser.rb b/lib/model/parser.rb index f81a3f8..f9da6f6 100644 --- a/lib/model/parser.rb +++ b/lib/model/parser.rb @@ -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 \ No newline at end of file diff --git a/lib/model/parsers/collada_parser.rb b/lib/model/parsers/collada_parser.rb new file mode 100644 index 0000000..44dc14d --- /dev/null +++ b/lib/model/parsers/collada_parser.rb @@ -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 \ No newline at end of file diff --git a/lib/model/parsers/wavefront_parser.rb b/lib/model/parsers/wavefront_parser.rb index 4ddd76e..c4566e5 100644 --- a/lib/model/parsers/wavefront_parser.rb +++ b/lib/model/parsers/wavefront_parser.rb @@ -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 diff --git a/lib/game_objects/model_loader.rb b/lib/model_cache.rb similarity index 75% rename from lib/game_objects/model_loader.rb rename to lib/model_cache.rb index 05eacdd..4757105 100644 --- a/lib/game_objects/model_loader.rb +++ b/lib/model_cache.rb @@ -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 diff --git a/lib/states/game_states/loading_state.rb b/lib/states/game_states/loading_state.rb index 3ce2da8..73a400e 100644 --- a/lib/states/game_states/loading_state.rb +++ b/lib/states/game_states/loading_state.rb @@ -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") diff --git a/maps/test_map.json b/maps/test_map.json index 62b4b0d..ecb45e0 100644 --- a/maps/test_map.json +++ b/maps/test_map.json @@ -23,7 +23,7 @@ "entities":[ { "package":"base", - "name":"tree", + "name":"evergreen_tree", "position": { "x":0, "y":0.6,