diff --git a/i-mic-fps.rb b/i-mic-fps.rb index f4df6d7..8de9caf 100644 --- a/i-mic-fps.rb +++ b/i-mic-fps.rb @@ -18,13 +18,16 @@ end BoundingBox = Struct.new(:min_x, :min_y, :min_z, :max_x, :max_y, :max_z) -$debug = true if ARGV.join.include?("--debug") +$debug = ARGV.join.include?("--debug") ? true : false + +require_relative "lib/managers/object_manager" +require_relative "lib/managers/light_manager" require_relative "lib/objects/light" -require_relative "lib/wavefront/parser" +require_relative "lib/objects/model" + require_relative "lib/wavefront/model" -require_relative "lib/wavefront/object" -require_relative "lib/wavefront/material" + require_relative "lib/window" MODEL_METER_SCALE = 0.001 # Objects exported from blender using the millimeter object scale will be close to 1 GL unit diff --git a/lib/managers/light_manager.rb b/lib/managers/light_manager.rb new file mode 100644 index 0000000..a820606 --- /dev/null +++ b/lib/managers/light_manager.rb @@ -0,0 +1,4 @@ +class IMICFPS + class LightManager + end +end diff --git a/lib/managers/object_manager.rb b/lib/managers/object_manager.rb new file mode 100644 index 0000000..3353722 --- /dev/null +++ b/lib/managers/object_manager.rb @@ -0,0 +1,20 @@ +class IMICFPS + TextureCoordinate = Struct.new(:u, :v, :weight) + Vertex = Struct.new(:x, :y, :z, :weight) + Point = Struct.new(:x, :y) + Color = Struct.new(:red, :green, :blue, :alpha) + + class ObjectManager + OBJECTS = [] + def self.add_object(model) + OBJECTS << model + end + + def self.find_object() + end + + def self.objects + OBJECTS + end + end +end diff --git a/lib/objects/model.rb b/lib/objects/model.rb new file mode 100644 index 0000000..1e7ce03 --- /dev/null +++ b/lib/objects/model.rb @@ -0,0 +1,97 @@ +class IMICFPS + class Model + def self.supported_models + ["Wavefront OBJ"] + end + + CACHE = {} + + include OpenGL + include GLU + + attr_accessor :x, :y, :z, :scale + attr_accessor :visible, :renderable + attr_accessor :x_rotation, :y_rotation, :z_rotation + + def initialize(type:, file_path:, x: 0, y: 0, z: 0, scale: MODEL_METER_SCALE, backface_culling: true) + @type = type + @file_path = file_path + @x,@y,@z,@scale = x,y,z,scale + @backface_culling = backface_culling + @visible = true + @renderable = true + @x_rotation,@y_rotation,@z_rotation = 0,0,0 + + @model = nil + + unless load_model_from_cache + case type + when :obj + p file_path + @model = Wavefront::Model.new(@file_path) + else + raise "Unsupported model type, supported models are: #{Model.supported_models.join(', ')}" + end + end + + cache_model + + ObjectManager.add_object(self) + + setup + + return self + end + + def setup + end + + def draw + handleGlError + + glEnable(GL_NORMALIZE) + glPushMatrix + glTranslatef(x,y,z) + glScalef(scale, scale, scale) + glRotatef(@x_rotation,1.0, 0, 0) + glRotatef(@y_rotation,0, 1.0, 0) + glRotatef(@z_rotation,0, 0, 1.0) + + handleGlError + @model.draw(@x, @y, @z, @scale, @backface_culling) + handleGlError + + glPopMatrix + handleGlError + end + + def update + end + + def load_model_from_cache + found = false + if CACHE[@type].is_a?(Hash) + if CACHE[@type][@file_path] + @model = CACHE[@type][@file_path] + puts "Used cached model for: #{@file_path.split('/').last}" + found = true + end + end + + return found + end + + def cache_model + CACHE[@type] = {} unless CACHE[@type].is_a?(Hash) + CACHE[@type][@file_path] = @model + end + + def handleGlError + e = glGetError() + if e != GL_NO_ERROR + $stderr.puts "OpenGL error in: #{gluErrorString(e)} (#{e})\n" + exit + end + end + end +end diff --git a/lib/wavefront/material.rb b/lib/wavefront/material.rb index 54125ce..c1928d7 100644 --- a/lib/wavefront/material.rb +++ b/lib/wavefront/material.rb @@ -6,9 +6,9 @@ class IMICFPS attr_reader :texture def initialize(name) @name = name - @ambient = Wavefront::Model::Color.new(1, 1, 1, 1) - @diffuse = Wavefront::Model::Color.new(1, 1, 1, 1) - @specular= Wavefront::Model::Color.new(1, 1, 1, 1) + @ambient = Color.new(1, 1, 1, 1) + @diffuse = Color.new(1, 1, 1, 1) + @specular= Color.new(1, 1, 1, 1) @texture = nil @texture_id = nil end diff --git a/lib/wavefront/model.rb b/lib/wavefront/model.rb index 4a06389..378743f 100644 --- a/lib/wavefront/model.rb +++ b/lib/wavefront/model.rb @@ -1,3 +1,7 @@ +require_relative "parser" +require_relative "object" +require_relative "material" + class IMICFPS class Wavefront class Model @@ -47,25 +51,7 @@ class IMICFPS end end - def handleGlError - e = glGetError() - if e != GL_NO_ERROR - $stderr.puts "OpenGL error in: #{gluErrorString(e)} (#{e})\n" - exit - end - end - - def draw(x, y, z, scale = MODEL_METER_SCALE, back_face_culling = true) - handleGlError - render(x,y,z, scale, back_face_culling) - handleGlError - end - - def render(x,y,z, scale, back_face_culling) - glEnable(GL_NORMALIZE) - glPushMatrix - glTranslatef(x,y,z) - glScalef(scale, scale, scale) + def draw(x,y,z, scale, back_face_culling) @objects.each_with_index do |o, i| glEnable(GL_CULL_FACE) if back_face_culling glEnable(GL_COLOR_MATERIAL) @@ -95,12 +81,11 @@ class IMICFPS # glBindTexture(GL_TEXTURE_2D, 0) glDisable(GL_TEXTURE_2D) end + render_bounding_box(o.bounding_box, o.debug_color) if $debug glDisable(GL_CULL_FACE) if back_face_culling glDisable(GL_COLOR_MATERIAL) - render_bounding_box(o.bounding_box, o.debug_color) if $debug end render_bounding_box(@bounding_box) if $debug - glPopMatrix $window.number_of_faces+=self.faces.size diff --git a/lib/wavefront/object.rb b/lib/wavefront/object.rb index 58ccf1a..dd74395 100644 --- a/lib/wavefront/object.rb +++ b/lib/wavefront/object.rb @@ -11,7 +11,7 @@ class IMICFPS @normals = [] @faces = [] @bounding_box = BoundingBox.new(nil,nil,nil, nil,nil,nil) - @debug_color = Parser::Color.new(1.0,0.0,0.0) + @debug_color = Color.new(1.0,0.0,0.0) # Faces array packs everything: # vertex = index[0] diff --git a/lib/wavefront/parser.rb b/lib/wavefront/parser.rb index b53623a..6c4beae 100644 --- a/lib/wavefront/parser.rb +++ b/lib/wavefront/parser.rb @@ -1,10 +1,6 @@ class IMICFPS class Wavefront module Parser - TextureCoordinate = Struct.new(:u, :v, :weight) - Vertex = Struct.new(:x, :y, :z, :weight) - Color = Struct.new(:red, :green, :blue, :alpha) - def parse lines = 0 @file.each_line do |line| diff --git a/lib/window.rb b/lib/window.rb index 03bb77e..68c71b8 100644 --- a/lib/window.rb +++ b/lib/window.rb @@ -3,7 +3,6 @@ class IMICFPS include OpenGL include GLU # include GLUT - Point = Struct.new(:x, :y) attr_accessor :number_of_faces, :needs_cursor @@ -19,15 +18,16 @@ class IMICFPS @delta_time = Gosu.milliseconds @number_of_faces = 0 @draw_skydome = true - @skydome = Wavefront::Model.new("objects/skydome.obj") - @plane = Wavefront::Model.new("objects/plane.obj") - @cube = Wavefront::Model.new("objects/cube.obj") - @model = Wavefront::Model.new("objects/biped.obj") - @tree = Wavefront::Model.new("objects/tree.obj") - @mega_model = Wavefront::Model.new("objects/sponza.obj") + Model.new(type: :obj, file_path: "objects/skydome.obj", x: 0, y: 0,z: 0, scale: 1, backface_culling: false) + Model.new(type: :obj, file_path: "objects/cube.obj", x: 0,y: 1,z: -2, scale: 0.0005) + Model.new(type: :obj, file_path: "objects/biped.obj", x: 1, y: 0, z: 0) + Model.new(type: :obj, file_path: "objects/tree.obj", x: 3) + Model.new(type: :obj, file_path: "objects/tree.obj", z: -5) + Model.new(type: :obj, file_path: "objects/tree.obj", x: -2, z: -6) + Model.new(type: :obj, file_path: "objects/sponza.obj", scale: 1, y: -0.2) - @camera = Wavefront::Model::Vertex.new(0,-1,0) - @camera_target = Wavefront::Model::Vertex.new(0,-1,0) + @camera = Vertex.new(0,-1,0) + @camera_target = Vertex.new(0,-1,0) @speed = 0.05 @old_speed = @speed @vertical_angle = 0.0 # | @@ -35,7 +35,7 @@ class IMICFPS self.mouse_x, self.mouse_y = Gosu.screen_width/2, Gosu.screen_height/2 @true_mouse = Point.new(Gosu.screen_width/2, Gosu.screen_height/2) @true_mouse_checked = 0 - @mouse_sesitivity = 5.0 + @mouse_sesitivity = 20.0 @initial_fov = 70.0 @crosshair_size = 10 @@ -81,22 +81,17 @@ class IMICFPS glMatrixMode(GL_MODELVIEW) # The modelview matrix is where object information is stored. glLoadIdentity - @camera_light.draw glEnable(GL_DEPTH_TEST) + @camera_light.draw glRotatef(@vertical_angle,1,0,0) glRotatef(@horizontal_angle,0,1,0) glTranslatef(@camera.x, @camera.y, @camera.z) # gluLookAt(@camera.x,@camera.y,@camera.z, @horizontal_angle,@vertical_angle,0, 0,1,0) - @skydome.draw(0,0,0, 1, false) if @draw_skydome - @cube.draw(0,1,-2, 0.0005) - @plane.draw(0,-1,-4, 0.0005, false) - @model.draw(1, 0, 0) - @tree.draw(5, 0, 0) - @tree.draw(5, 0, 3) - @tree.draw(3, 0, 10) - # @mega_model.draw(0,0,0, 1) + ObjectManager.objects.each do |object| + object.draw if object.visible && object.renderable + end end # Draw crosshair @@ -109,6 +104,7 @@ class IMICFPS end def update + @last_frame_time = Gosu.milliseconds @text = "OpenGL Vendor: #{glGetString(GL_VENDOR)}~ OpenGL Renderer: #{glGetString(GL_RENDERER)} ~ OpenGL Version: #{glGetString(GL_VERSION)}~ @@ -122,7 +118,10 @@ class IMICFPS ~ Draw Skydome: #{@draw_skydome}~ Debug mode: #{$debug}~" - @last_frame_time = Gosu.milliseconds + + ObjectManager.objects.each do |object| + object.update + end if @true_mouse_checked > 2 @horizontal_angle-=Float(@true_mouse.x-self.mouse_x)/@mouse_sesitivity