diff --git a/lib/objects/model.rb b/lib/objects/model.rb index 1e7ce03..5ab3c78 100644 --- a/lib/objects/model.rb +++ b/lib/objects/model.rb @@ -12,6 +12,7 @@ class IMICFPS attr_accessor :x, :y, :z, :scale attr_accessor :visible, :renderable attr_accessor :x_rotation, :y_rotation, :z_rotation + attr_reader :model, :name, :debug_color def initialize(type:, file_path:, x: 0, y: 0, z: 0, scale: MODEL_METER_SCALE, backface_culling: true) @type = type @@ -21,20 +22,23 @@ class IMICFPS @visible = true @renderable = true @x_rotation,@y_rotation,@z_rotation = 0,0,0 + @name = file_path.split("/").last.split(".").first + @debug_color = Color.new(rand(0.0..1.0), rand(0.0..1.0), rand(0.0..1.0)) + @temp_bounding_box = BoundingBox.new(0,0,0, 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 + + cache_model end - cache_model ObjectManager.add_object(self) @@ -51,8 +55,13 @@ class IMICFPS glEnable(GL_NORMALIZE) glPushMatrix + # Render bounding boxes before transformation is applied + render_bounding_box(@model.bounding_box) if $debug + @model.objects.each {|o| render_bounding_box(o.bounding_box, o.debug_color)} if $debug + 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) @@ -66,6 +75,16 @@ class IMICFPS end def update + ObjectManager.objects.each do |a| + ObjectManager.objects.each do |b| + next if a == b + if a.intersect(a.model.bounding_box, b.model.bounding_box) + if a.name == "tree" + a.y_rotation+=0.1 + end + end + end + end end def load_model_from_cache @@ -86,6 +105,102 @@ class IMICFPS CACHE[@type][@file_path] = @model end + # Do two Axis Aligned Bounding Boxes intersect? + def intersect(a, b) + a = normalize_bounding_box(a) + b = normalize_bounding_box(b) + if (a.min_x <= b.max_x && a.max_x >= b.min_x) && + (a.min_y <= b.max_y && a.max_y >= b.min_y) && + (a.min_z <= b.max_z && a.max_z >= b.min_z) + true + else + false + end + end + + def normalize_bounding_box(bounding_box) + @temp_bounding_box.min_x = bounding_box.min_x*scale+x + @temp_bounding_box.min_y = bounding_box.min_y*scale+y + @temp_bounding_box.min_z = bounding_box.min_z*scale+z + + @temp_bounding_box.max_x = bounding_box.max_x*scale+x + @temp_bounding_box.max_y = bounding_box.max_y*scale+y + @temp_bounding_box.max_z = bounding_box.max_z*scale+z + return @temp_bounding_box + end + + def render_bounding_box(bounding_box, color = @debug_color) + # TODO: Minimize number of calls in here + bounding_box = normalize_bounding_box(bounding_box) + puts bounding_box + puts + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) + glBegin(GL_TRIANGLES) + # TOP + glNormal3f(0,1,0) + glColor3f(color.red, color.green, color.blue) + glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.max_z) + glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.min_z) + glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.min_z) + + glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.max_z) + glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.max_z) + glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.min_z) + + # BOTTOM + glNormal3f(0,-1,0) + glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.min_z) + glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.max_z) + glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.max_z) + + glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.min_z) + glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.min_z) + glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.max_z) + + # RIGHT SIDE + glNormal3f(0,0,1) + glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.max_z) + glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.min_z) + glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.min_z) + + glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.max_z) + glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.min_z) + glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.max_z) + + # LEFT SIDE + glNormal3f(1,0,0) + glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.max_z) + glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.min_z) + glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.min_z) + + glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.max_z) + glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.min_z) + glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.max_z) + + # FRONT + glNormal3f(-1,0,0) + glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.max_z) + glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.max_z) + glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.max_z) + + glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.max_z) + glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.max_z) + glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.max_z) + + # BACK + glNormal3f(-1,0,0) + glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.min_z) + glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.min_z) + glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.min_z) + + glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.min_z) + glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.min_z) + glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.min_z) + glEnd + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) + end + def handleGlError e = glGetError() if e != GL_NO_ERROR diff --git a/lib/wavefront/model.rb b/lib/wavefront/model.rb index 378743f..077f621 100644 --- a/lib/wavefront/model.rb +++ b/lib/wavefront/model.rb @@ -12,6 +12,7 @@ class IMICFPS attr_accessor :objects, :materials, :vertexes, :texures, :normals, :faces attr_accessor :x, :y, :z + attr_reader :bounding_box def initialize(object = "objects/cube.obj") @x, @y, @z = 0, 0, 0 @@ -30,7 +31,6 @@ class IMICFPS @smoothing= 0 @bounding_box = BoundingBox.new(nil,nil,nil, nil,nil,nil) - @debug_color = Color.new(rand(0.0..1.0), rand(0.0..1.0), rand(0.0..1.0)) start_time = Time.now parse puts "#{object.split('/').last} took #{(Time.now-start_time).round(2)} seconds to parse" @@ -81,83 +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) end - render_bounding_box(@bounding_box) if $debug - - $window.number_of_faces+=self.faces.size end - - def render_bounding_box(bounding_box, color = @debug_color) - # TODO: Minimize number of calls in here - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) - glBegin(GL_TRIANGLES) - # TOP - glNormal3f(0,1,0) - glColor3f(color.red, color.green, color.blue) - glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.max_z) - glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.min_z) - glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.min_z) - - glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.max_z) - glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.max_z) - glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.min_z) - - # BOTTOM - glNormal3f(0,-1,0) - glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.min_z) - glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.max_z) - glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.max_z) - - glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.min_z) - glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.min_z) - glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.max_z) - - # RIGHT SIDE - glNormal3f(0,0,1) - glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.max_z) - glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.min_z) - glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.min_z) - - glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.max_z) - glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.min_z) - glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.max_z) - - # LEFT SIDE - glNormal3f(1,0,0) - glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.max_z) - glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.min_z) - glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.min_z) - - glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.max_z) - glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.min_z) - glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.max_z) - - # FRONT - glNormal3f(-1,0,0) - glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.max_z) - glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.max_z) - glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.max_z) - - glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.max_z) - glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.max_z) - glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.max_z) - - # BACK - glNormal3f(-1,0,0) - glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.min_z) - glVertex3f(bounding_box.min_x, bounding_box.min_y, bounding_box.min_z) - glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.min_z) - - glVertex3f(bounding_box.max_x, bounding_box.min_y, bounding_box.min_z) - glVertex3f(bounding_box.min_x, bounding_box.max_y, bounding_box.min_z) - glVertex3f(bounding_box.max_x, bounding_box.max_y, bounding_box.min_z) - glEnd - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) - end end end end diff --git a/lib/window.rb b/lib/window.rb index 68c71b8..159030f 100644 --- a/lib/window.rb +++ b/lib/window.rb @@ -18,13 +18,13 @@ class IMICFPS @delta_time = Gosu.milliseconds @number_of_faces = 0 @draw_skydome = true - Model.new(type: :obj, file_path: "objects/skydome.obj", x: 0, y: 0,z: 0, scale: 1, backface_culling: false) + @skydome = 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) + # 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 = Vertex.new(0,-1,0) @camera_target = Vertex.new(0,-1,0) @@ -63,10 +63,7 @@ class IMICFPS $stderr.puts "OpenGL error in: #{gluErrorString(e)} (#{e})\n" exit end - render - end - def render gl do glClearColor(0,0.2,0.5,1) # skyish blue glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # clear the screen and the depth buffer @@ -124,8 +121,8 @@ class IMICFPS end if @true_mouse_checked > 2 - @horizontal_angle-=Float(@true_mouse.x-self.mouse_x)/@mouse_sesitivity - @vertical_angle-=Float(@true_mouse.y-self.mouse_y)/@mouse_sesitivity + @horizontal_angle-=Float(@true_mouse.x-self.mouse_x)/(@mouse_sesitivity*@initial_fov)*70 + @vertical_angle-=Float(@true_mouse.y-self.mouse_y)/(@mouse_sesitivity*@initial_fov)*70 @horizontal_angle %= 360.0 @vertical_angle = @vertical_angle.clamp(-90.0, 90.0) else