diff --git a/i-mic-fps.rb b/i-mic-fps.rb index 51a7f02..626dd46 100644 --- a/i-mic-fps.rb +++ b/i-mic-fps.rb @@ -27,6 +27,7 @@ require_relative "lib/managers/light_manager" require_relative "lib/objects/light" require_relative "lib/objects/camera" require_relative "lib/objects/model" +require_relative "lib/objects/terrain" require_relative "lib/wavefront/model" diff --git a/lib/objects/camera.rb b/lib/objects/camera.rb index bcbc9bc..69efce8 100644 --- a/lib/objects/camera.rb +++ b/lib/objects/camera.rb @@ -37,15 +37,14 @@ class IMICFPS # Calculates aspect ratio of the window. Gets perspective view. 45 is degree viewing angle, (0.1, 100) are ranges how deep can we draw into the screen gluPerspective(@field_of_view, $window.width / $window.height, 0.1, 1000.0) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) + glRotatef(@vertical_angle,1,0,0) + glRotatef(@horizontal_angle,0,1,0) + glTranslatef(@x, @y, @z) glMatrixMode(GL_MODELVIEW) # The modelview matrix is where object information is stored. glLoadIdentity glEnable(GL_DEPTH_TEST) - - glRotatef(@vertical_angle,1,0,0) - glRotatef(@horizontal_angle,0,1,0) - glTranslatef(@x, @y, @z) end def update @@ -122,10 +121,10 @@ class IMICFPS @mouse_sensitivity = 20.0 when Gosu::MsWheelUp @field_of_view += 1 - @field_of_view = @field_of_view.clamp(1, 179) + @field_of_view = @field_of_view.clamp(1, 100) when Gosu::MsWheelDown @field_of_view -= 1 - @field_of_view = @field_of_view.clamp(1, 179) + @field_of_view = @field_of_view.clamp(1, 100) end end end diff --git a/lib/objects/model.rb b/lib/objects/model.rb index 0db2e05..7e57b98 100644 --- a/lib/objects/model.rb +++ b/lib/objects/model.rb @@ -14,7 +14,7 @@ class IMICFPS 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) + def initialize(type:, file_path:, x: 0, y: 0, z: 0, scale: MODEL_METER_SCALE, backface_culling: true, auto_manage: true) @type = type @file_path = file_path @x,@y,@z,@scale = x,y,z,scale @@ -24,7 +24,6 @@ class IMICFPS @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 @@ -40,7 +39,7 @@ class IMICFPS end - ObjectManager.add_object(self) + ObjectManager.add_object(self) if auto_manage setup @@ -73,16 +72,16 @@ class IMICFPS end def update - ObjectManager.objects.each do |a| - ObjectManager.objects.each do |b| - next if a == b - next if b.name == "skydome" - if a.intersect(a.model.bounding_box, b.model.bounding_box) - if a.name == "tree" - puts "#{b.name} is touching me" - a.y_rotation+=0.01 - end - end + ObjectManager.objects.each do |b| + next if b.name == self.name + raise if b.name == self.name + + if self.intersect(self.model.bounding_box, b.model.bounding_box) + self.y_rotation+=0.02 + + puts "#{b.name} is touching me" + else + # puts "!=! No Collision" end end end @@ -109,95 +108,106 @@ class IMICFPS 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) - return true - else - return 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 + puts "bounding boxes match!" if a == b + # maxx1 > minx2 && minx1 < maxx2 # && maxy1 > miny1 && miny1 < maxy2 + if (a.max_x >= b.max_x && a.min_x <= b.max_x) && (a.max_y >= b.min_y && a.min_y <= b.max_y) && (a.max_z >= b.min_z && a.min_z <= b.max_z) + # puts a + # puts b + # exit + return true + end + end - @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 normalize_bounding_box(box) + temp = BoundingBox.new + temp.min_x = box.min_x.to_f*scale+x + temp.min_y = box.min_y.to_f*scale+y + temp.min_z = box.min_z.to_f*scale+z - def render_bounding_box(bounding_box, color = @debug_color) + temp.max_x = box.max_x.to_f*scale+x + temp.max_y = box.max_y.to_f*scale+y + temp.max_z = box.max_z.to_f*scale+z + + # puts "b: #{box}, Temp: #{temp}" + return temp + end + + def render_bounding_box(box, color = @debug_color) # TODO: Minimize number of calls in here - bounding_box = normalize_bounding_box(bounding_box) + box = normalize_bounding_box(box) - 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) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) + glBegin(GL_LINES) + glColor3f(0,0,1.0) + glVertex3f(box.min_x, box.min_y, box.min_z) + glColor3f(1.0,0,0) + glVertex3f(box.max_x, box.max_y, box.max_z) + glEnd + glBegin(GL_TRIANGLES) + # TOP + glNormal3f(0,1,0) + glColor3f(color.red, color.green, color.blue) + glVertex3f(box.min_x, box.max_y, box.max_z) + glVertex3f(box.min_x, box.max_y, box.min_z) + glVertex3f(box.max_x, box.max_y, 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) + glVertex3f(box.min_x, box.max_y, box.max_z) + glVertex3f(box.max_x, box.max_y, box.max_z) + glVertex3f(box.max_x, box.max_y, 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) + # BOTTOM + glNormal3f(0,-1,0) + glVertex3f(box.max_x, box.min_y, box.min_z) + glVertex3f(box.max_x, box.min_y, box.max_z) + glVertex3f(box.min_x, box.min_y, 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) + glVertex3f(box.max_x, box.min_y, box.min_z) + glVertex3f(box.min_x, box.min_y, box.min_z) + glVertex3f(box.min_x, box.min_y, 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) + # RIGHT SIDE + glNormal3f(0,0,1) + glVertex3f(box.min_x, box.max_y, box.max_z) + glVertex3f(box.min_x, box.max_y, box.min_z) + glVertex3f(box.min_x, box.min_y, 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) + glVertex3f(box.min_x, box.min_y, box.max_z) + glVertex3f(box.min_x, box.min_y, box.min_z) + glVertex3f(box.min_x, box.max_y, 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) + # LEFT SIDE + glNormal3f(1,0,0) + glVertex3f(box.max_x, box.max_y, box.max_z) + glVertex3f(box.max_x, box.max_y, box.min_z) + glVertex3f(box.max_x, box.min_y, 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) + glVertex3f(box.max_x, box.min_y, box.max_z) + glVertex3f(box.max_x, box.min_y, box.min_z) + glVertex3f(box.max_x, box.max_y, 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) + # FRONT + glNormal3f(-1,0,0) + glVertex3f(box.min_x, box.max_y, box.max_z) + glVertex3f(box.max_x, box.max_y, box.max_z) + glVertex3f(box.max_x, box.min_y, 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) + glVertex3f(box.min_x, box.max_y, box.max_z) + glVertex3f(box.max_x, box.min_y, box.max_z) + glVertex3f(box.min_x, box.min_y, 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) + # BACK + glNormal3f(-1,0,0) + glVertex3f(box.max_x, box.min_y, box.min_z) + glVertex3f(box.min_x, box.min_y, box.min_z) + glVertex3f(box.min_x, box.max_y, 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 + glVertex3f(box.max_x, box.min_y, box.min_z) + glVertex3f(box.min_x, box.max_y, box.min_z) + glVertex3f(box.max_x, box.max_y, box.min_z) + glEnd + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) + end def handleGlError e = glGetError() diff --git a/lib/objects/terrain.rb b/lib/objects/terrain.rb new file mode 100644 index 0000000..db03020 --- /dev/null +++ b/lib/objects/terrain.rb @@ -0,0 +1,29 @@ +class IMICFPS + class Terrain + include OpenGL + def initialize(size:, heightmap: nil) + @size = size + @heightmap = heightmap + end + + def draw + height = 0 + glEnable(GL_COLOR_MATERIAL) + + glBegin(GL_TRIANGLES) + glNormal3f(0,1,0) + glColor3f(1, 0.5, 0.0) + glVertex3f(-@size,height,-@size) + glVertex3f(-@size,height,@size) + glVertex3f(@size,height,@size) + + glColor3f(0, 0.5, 0.0) + glVertex3f(@size,height,@size) + glVertex3f(@size,height,-@size) + glVertex3f(-@size,height,-@size) + glEnd + + glDisable(GL_COLOR_MATERIAL) + end + end +end diff --git a/lib/wavefront/model.rb b/lib/wavefront/model.rb index 73b9801..55ac1be 100644 --- a/lib/wavefront/model.rb +++ b/lib/wavefront/model.rb @@ -31,7 +31,7 @@ class IMICFPS @faces = [] @smoothing= 0 - @bounding_box = BoundingBox.new(nil,nil,nil, nil,nil,nil) + @bounding_box = BoundingBox.new(0,0,0, 0,0,0) start_time = Time.now parse puts "#{@file_path.split('/').last} took #{(Time.now-start_time).round(2)} seconds to parse" diff --git a/lib/wavefront/object.rb b/lib/wavefront/object.rb index 94b4a12..a3ed2a7 100644 --- a/lib/wavefront/object.rb +++ b/lib/wavefront/object.rb @@ -11,7 +11,7 @@ class IMICFPS @textures = [] @normals = [] @faces = [] - @bounding_box = BoundingBox.new(nil,nil,nil, nil,nil,nil) + @bounding_box = BoundingBox.new(0,0,0, 0,0,0) @debug_color = Color.new(1.0,0.0,0.0) # Faces array packs everything: diff --git a/lib/wavefront/parser.rb b/lib/wavefront/parser.rb index 737d2be..5617e76 100644 --- a/lib/wavefront/parser.rb +++ b/lib/wavefront/parser.rb @@ -49,6 +49,10 @@ class IMICFPS end puts "Total Lines: #{lines}" + calculate_bounding_box(@vertices, @bounding_box) + @objects.each do |o| + calculate_bounding_box(o.vertices, o.bounding_box) + end end def parse_mtllib @@ -114,8 +118,6 @@ class IMICFPS else raise end - recalculate_bounding_box(vert, @bounding_box) - recalculate_bounding_box(vert, @current_object.bounding_box) @current_object.vertices << vert @vertices << vert end @@ -146,9 +148,9 @@ class IMICFPS @uvs << texture end - def recalculate_bounding_box(vertex, bounding_box) - # Set a default relative to the model + def calculate_bounding_box(vertices, bounding_box) unless bounding_box.min_x.is_a?(Float) + vertex = vertices.first bounding_box.min_x = vertex.x bounding_box.min_y = vertex.y bounding_box.min_z = vertex.z @@ -158,13 +160,15 @@ class IMICFPS bounding_box.max_z = vertex.z end - bounding_box.min_x = vertex.x if vertex.x < bounding_box.min_x - bounding_box.min_y = vertex.y if vertex.y < bounding_box.min_y - bounding_box.min_z = vertex.z if vertex.z < bounding_box.min_z + vertices.each do |vertex| + bounding_box.min_x = vertex.x if vertex.x < bounding_box.min_x + bounding_box.min_y = vertex.y if vertex.y < bounding_box.min_y + bounding_box.min_z = vertex.z if vertex.z < bounding_box.min_z - bounding_box.max_x = vertex.x if vertex.x > bounding_box.max_x - bounding_box.max_y = vertex.y if vertex.y > bounding_box.max_y - bounding_box.max_z = vertex.z if vertex.z > bounding_box.max_z + bounding_box.max_x = vertex.x if vertex.x > bounding_box.max_x + bounding_box.max_y = vertex.y if vertex.y > bounding_box.max_y + bounding_box.max_z = vertex.z if vertex.z > bounding_box.max_z + end end end end diff --git a/lib/window.rb b/lib/window.rb index 6abb634..3830424 100644 --- a/lib/window.rb +++ b/lib/window.rb @@ -18,14 +18,15 @@ class IMICFPS @delta_time = Gosu.milliseconds @number_of_faces = 0 @draw_skydome = true - @skydome = Model.new(type: :obj, file_path: "objects/skydome.obj", x: 0, y: 0,z: 0, scale: 1, backface_culling: false) - @actor = 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) + @skydome = Model.new(type: :obj, file_path: "objects/skydome.obj", x: 0, y: 0,z: 0, scale: 1, backface_culling: false, auto_manage: false) + @actor = Model.new(type: :obj, file_path: "objects/biped.obj", x: 0, y: 0, z: -2) + Model.new(type: :obj, file_path: "objects/tree.obj", x: 0, y: 0, z: -10) # 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) + @terrain = Terrain.new(size: 100) - @camera = Camera.new + @camera = Camera.new(x: 0, y: -2, z: 1) @camera.bind_model(@actor) @crosshair_size = 10 @@ -54,10 +55,11 @@ class IMICFPS light.draw end @camera.draw - + @skydome.draw if @skydome.renderable ObjectManager.objects.each do |object| object.draw if object.visible && object.renderable end + @terrain.draw end # Draw crosshair @@ -78,8 +80,8 @@ class IMICFPS ~ Vertical Angle: #{@camera.vertical_angle.round(2)} Horizontal Angle: #{@camera.horizontal_angle.round(2)} ~ Camera X:#{@camera.x.round(2)} Y:#{@camera.y.round(2)} Z:#{@camera.z.round(2)} ~ - Actor X:#{@camera.bound_model.x.round(2)} Y:#{@camera.bound_model.y.round(2)} Z:#{@camera.bound_model.z.round(2)} ~ - FOV: #{@camera.field_of_view} ~ + #{if @camera.bound_model then "Actor X:#{@camera.bound_model.x.round(2)} Y:#{@camera.bound_model.y.round(2)} Z:#{@camera.bound_model.z.round(2)}";end} ~ + Field Of View: #{@camera.field_of_view} ~ Mouse Sesitivity: #{@camera.mouse_sensitivity} ~ Faces: #{@number_of_faces} ~ Last Frame: #{delta_time}ms (#{Gosu.fps} fps)~