From 35b5ee948a8f98ca55ca64abbf66bd47eb13bef5 Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Thu, 20 Sep 2018 09:07:39 -0500 Subject: [PATCH] Moved OpenGL renderering code into its own class for future optimizations --- i-mic-fps.rb | 1 + lib/objects/game_object.rb | 176 +-------------------- lib/objects/player.rb | 15 +- lib/objects/terrain.rb | 1 + lib/objects/tree.rb | 8 +- lib/renderer/renderer.rb | 274 +++++++++++++++++++++++++++++++++ lib/states/game_states/game.rb | 7 +- lib/states/menu.rb | 2 +- lib/wavefront/model.rb | 51 +----- 9 files changed, 294 insertions(+), 241 deletions(-) create mode 100644 lib/renderer/renderer.rb diff --git a/i-mic-fps.rb b/i-mic-fps.rb index 23d4bb5..77b43ce 100644 --- a/i-mic-fps.rb +++ b/i-mic-fps.rb @@ -44,6 +44,7 @@ $debug = ARGV.join.include?("--debug") ? true : false require_relative "lib/common_methods" require_relative "lib/managers/object_manager" require_relative "lib/managers/light_manager" +require_relative "lib/renderer/renderer" require_relative "lib/states/game_state" require_relative "lib/states/game_states/loading_state" diff --git a/lib/objects/game_object.rb b/lib/objects/game_object.rb index af49ee6..b4d494e 100644 --- a/lib/objects/game_object.rb +++ b/lib/objects/game_object.rb @@ -60,26 +60,8 @@ class IMICFPS def setup end + # Not advisable to put OpenGL code here, instead put it in Renderer. def draw - handleGlError - - 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) - 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 @@ -117,162 +99,6 @@ class IMICFPS return temp end - def render_bounding_box(box, color = @debug_color) - box = normalize_bounding_box(box) - - glEnableClientState(GL_VERTEX_ARRAY) - glEnableClientState(GL_COLOR_ARRAY) - glEnableClientState(GL_NORMAL_ARRAY) - - _normals = [ - 0,1,0, - 0,1,0, - 0,1,0, - 0,1,0, - 0,1,0, - 0,1,0, - - 0,-1,0, - 0,-1,0, - 0,-1,0, - 0,-1,0, - 0,-1,0, - 0,-1,0, - - 0,0,1, - 0,0,1, - 0,0,1, - 0,0,1, - 0,0,1, - 0,0,1, - - 1,0,0, - 1,0,0, - 1,0,0, - 1,0,0, - 1,0,0, - 1,0,0, - - -1,0,0, - -1,0,0, - -1,0,0, - -1,0,0, - -1,0,0, - -1,0,0, - - -1,0,0, - -1,0,0, - -1,0,0, - - -1,0,0, - -1,0,0, - -1,0,0 - ].pack("f*") - _colors = [ - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue, - color.red, color.green, color.blue - ].pack("f*") - _vertices = [ - box.min_x, box.max_y, box.max_z, - box.min_x, box.max_y, box.min_z, - box.max_x, box.max_y, box.min_z, - - box.min_x, box.max_y, box.max_z, - box.max_x, box.max_y, box.max_z, - box.max_x, box.max_y, box.min_z, - - box.max_x, box.min_y, box.min_z, - box.max_x, box.min_y, box.max_z, - box.min_x, box.min_y, box.max_z, - - box.max_x, box.min_y, box.min_z, - box.min_x, box.min_y, box.min_z, - box.min_x, box.min_y, box.max_z, - - box.min_x, box.max_y, box.max_z, - box.min_x, box.max_y, box.min_z, - box.min_x, box.min_y, box.min_z, - - box.min_x, box.min_y, box.max_z, - box.min_x, box.min_y, box.min_z, - box.min_x, box.max_y, box.max_z, - - box.max_x, box.max_y, box.max_z, - box.max_x, box.max_y, box.min_z, - box.max_x, box.min_y, box.min_z, - - box.max_x, box.min_y, box.max_z, - box.max_x, box.min_y, box.min_z, - box.max_x, box.max_y, box.max_z, - - box.min_x, box.max_y, box.max_z, - box.max_x, box.max_y, box.max_z, - box.max_x, box.min_y, box.max_z, - - box.min_x, box.max_y, box.max_z, - box.max_x, box.min_y, box.max_z, - box.min_x, box.min_y, box.max_z, - - box.max_x, box.min_y, box.min_z, - box.min_x, box.min_y, box.min_z, - box.min_x, box.max_y, box.min_z, - - box.max_x, box.min_y, box.min_z, - box.min_x, box.max_y, box.min_z, - box.max_x, box.max_y, box.min_z - ] - _vertices_size = _vertices.size - _vertices = _vertices.pack("f*") - - glVertexPointer(3, GL_FLOAT, 0, _vertices) - glColorPointer(3, GL_FLOAT, 0, _colors) - glNormalPointer(GL_FLOAT, 0, _normals) - - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) - glDisable(GL_LIGHTING) - glDrawArrays(GL_TRIANGLES, 0, _vertices_size/3) - glEnable(GL_LIGHTING) - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) - - glDisableClientState(GL_VERTEX_ARRAY) - glDisableClientState(GL_COLOR_ARRAY) - glDisableClientState(GL_NORMAL_ARRAY) - end - def handleGlError e = glGetError() if e != GL_NO_ERROR diff --git a/lib/objects/player.rb b/lib/objects/player.rb index 45f3ccb..813ede0 100644 --- a/lib/objects/player.rb +++ b/lib/objects/player.rb @@ -38,8 +38,7 @@ class IMICFPS def draw_nameplate _height = (@name_image.height/@devisor) _width = (@name_image.width/@devisor)/2 - _x = @x - _y = normalize_bounding_box(model.bounding_box).max_y+0.05 + _y = 2#normalize_bounding_box(model.bounding_box).max_y+0.05 glPushMatrix glDisable(GL_LIGHTING) glEnable(GL_COLOR_MATERIAL) @@ -51,27 +50,27 @@ class IMICFPS glColor3f(1.0,1.0,1.0) # TOP LEFT glTexCoord2f(0, 0) - glVertex3f(_x-_width,_y+_height,@z) + glVertex3f(0-_width,_y+_height,0) # TOP RIGHT glTexCoord2f(1, 0) - glVertex3f(_x+_width, _y+_height,@z) + glVertex3f(0+_width, _y+_height,0) # BOTTOM LEFT glTexCoord2f(0, 1) - glVertex3f(_x-_width,_y,@z) + glVertex3f(0-_width,_y,0) # BOTTOM LEFT glTexCoord2f(0, 1) - glVertex3f(_x-_width,_y,@z) + glVertex3f(0-_width,_y,0) # BOTTOM RIGHT glTexCoord2f(1, 1) - glVertex3f(_x+_width, _y,@z) + glVertex3f(0+_width, _y,0) # TOP RIGHT glTexCoord2f(1, 0) - glVertex3f(_x+_width,_y+_height,@z) + glVertex3f(0+_width,_y+_height,0) glEnd # glDisable(GL_BLEND) glDisable(GL_TEXTURE_2D) diff --git a/lib/objects/terrain.rb b/lib/objects/terrain.rb index 31bf1b1..e505cf2 100644 --- a/lib/objects/terrain.rb +++ b/lib/objects/terrain.rb @@ -2,6 +2,7 @@ class IMICFPS class Terrain < GameObject def setup bind_model(ModelLoader.new(type: :obj, file_path: "objects/randomish_terrain.obj", game_object: self)) + # bind_model(ModelLoader.new(type: :obj, file_path: "/home/cyberarm/Documents/blends/untitled.obj", game_object: self)) self.scale = 1 @nearest_vertex_lookup = {} diff --git a/lib/objects/tree.rb b/lib/objects/tree.rb index 46cdfbb..0aeea5b 100644 --- a/lib/objects/tree.rb +++ b/lib/objects/tree.rb @@ -3,9 +3,11 @@ class IMICFPS def setup bind_model(ModelLoader.new(type: :obj, file_path: "objects/tree.obj", game_object: self)) vert = @terrain.find_nearest_vertex(self, 4.5) - self.x = vert.x - self.y = vert.y - self.z = vert.z + if vert + self.x = vert.x + self.y = vert.y + self.z = vert.z + end end # def update diff --git a/lib/renderer/renderer.rb b/lib/renderer/renderer.rb new file mode 100644 index 0000000..616ca38 --- /dev/null +++ b/lib/renderer/renderer.rb @@ -0,0 +1,274 @@ +class IMICFPS + class Renderer + include OpenGL + include GLU + + def initialize + @bounding_boxes = {normals: [], colors: [], vertices: []} + end + + def draw + i = 0 + draw_bounding_boxes if $debug + $window.number_of_faces+=@bounding_boxes[:vertices].size/3 if $debug + @bounding_boxes.clear + ObjectManager.objects.each do |object| + if object.visible && object.renderable + draw_object(object) + i+=1 + end + end + + end + + def draw_object(object) + handleGlError + + glEnable(GL_NORMALIZE) + glPushMatrix + # Render bounding boxes before transformation is applied + create_bounding_box(object, object.model.bounding_box) if $debug + object.model.objects.each {|o| create_bounding_box(object, o.bounding_box, o.debug_color)} if $debug + + glTranslatef(object.x, object.y, object.z) + glRotatef(object.x_rotation,1.0, 0, 0) + glRotatef(object.y_rotation,0, 1.0, 0) + glRotatef(object.z_rotation,0, 0, 1.0) + + handleGlError + draw_mesh(object.model) + object.draw + # object.model.draw(object.x, object.y, object.z, object.scale, object.backface_culling) + handleGlError + + glPopMatrix + handleGlError + end + + def draw_mesh(model) + # x,y,z, scale, back_face_culling + model.objects.each_with_index do |o, i| + glEnable(GL_CULL_FACE) if model.game_object.backface_culling + glEnable(GL_COLOR_MATERIAL) + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE) + glShadeModel(GL_FLAT) unless o.faces.first[4] + glShadeModel(GL_SMOOTH) if o.faces.first[4] + glEnableClientState(GL_VERTEX_ARRAY) + glEnableClientState(GL_COLOR_ARRAY) + glEnableClientState(GL_NORMAL_ARRAY) + if model.model_has_texture + glEnable(GL_TEXTURE_2D) + glBindTexture(GL_TEXTURE_2D, model.materials[model.textured_material].texture_id) + glEnableClientState(GL_TEXTURE_COORD_ARRAY) + glTexCoordPointer(3, GL_FLOAT, 0, o.flattened_textures) + end + glVertexPointer(4, GL_FLOAT, 0, o.flattened_vertices) + glColorPointer(3, GL_FLOAT, 0, o.flattened_materials) + glNormalPointer(GL_FLOAT, 0, o.flattened_normals) + + glDrawArrays(GL_TRIANGLES, 0, o.flattened_vertices_size/4) + + if $debug + glDisable(GL_LIGHTING) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) + glPolygonOffset(2, 0.5) + glLineWidth(3) + glDrawArrays(GL_TRIANGLES, 0, o.flattened_vertices_size/4) + glLineWidth(1) + glPolygonOffset(0, 0) + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) + glEnable(GL_LIGHTING) + end + + glDisableClientState(GL_VERTEX_ARRAY) + glDisableClientState(GL_COLOR_ARRAY) + glDisableClientState(GL_NORMAL_ARRAY) + if model.model_has_texture + glDisableClientState(GL_TEXTURE_COORD_ARRAY) + # glBindTexture(GL_TEXTURE_2D, 0) + glDisable(GL_TEXTURE_2D) + end + glDisable(GL_CULL_FACE) if model.game_object.backface_culling + glDisable(GL_COLOR_MATERIAL) + end + $window.number_of_faces+=model.faces.size + end + + def create_bounding_box(object, box, color = nil) + color ||= object.debug_color + box = object.normalize_bounding_box(box) + + @bounding_boxes[:normals] ||= [] + @bounding_boxes[:colors] ||= [] + @bounding_boxes[:vertices] ||= [] + + @bounding_boxes[:normals] << [ + 0,1,0, + 0,1,0, + 0,1,0, + 0,1,0, + 0,1,0, + 0,1,0, + + 0,-1,0, + 0,-1,0, + 0,-1,0, + 0,-1,0, + 0,-1,0, + 0,-1,0, + + 0,0,1, + 0,0,1, + 0,0,1, + 0,0,1, + 0,0,1, + 0,0,1, + + 1,0,0, + 1,0,0, + 1,0,0, + 1,0,0, + 1,0,0, + 1,0,0, + + -1,0,0, + -1,0,0, + -1,0,0, + -1,0,0, + -1,0,0, + -1,0,0, + + -1,0,0, + -1,0,0, + -1,0,0, + + -1,0,0, + -1,0,0, + -1,0,0 + ] + @bounding_boxes[:colors] << [ + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue, + color.red, color.green, color.blue + ] + @bounding_boxes[:vertices] << [ + box.min_x, box.max_y, box.max_z, + box.min_x, box.max_y, box.min_z, + box.max_x, box.max_y, box.min_z, + + box.min_x, box.max_y, box.max_z, + box.max_x, box.max_y, box.max_z, + box.max_x, box.max_y, box.min_z, + + box.max_x, box.min_y, box.min_z, + box.max_x, box.min_y, box.max_z, + box.min_x, box.min_y, box.max_z, + + box.max_x, box.min_y, box.min_z, + box.min_x, box.min_y, box.min_z, + box.min_x, box.min_y, box.max_z, + + box.min_x, box.max_y, box.max_z, + box.min_x, box.max_y, box.min_z, + box.min_x, box.min_y, box.min_z, + + box.min_x, box.min_y, box.max_z, + box.min_x, box.min_y, box.min_z, + box.min_x, box.max_y, box.max_z, + + box.max_x, box.max_y, box.max_z, + box.max_x, box.max_y, box.min_z, + box.max_x, box.min_y, box.min_z, + + box.max_x, box.min_y, box.max_z, + box.max_x, box.min_y, box.min_z, + box.max_x, box.max_y, box.max_z, + + box.min_x, box.max_y, box.max_z, + box.max_x, box.max_y, box.max_z, + box.max_x, box.min_y, box.max_z, + + box.min_x, box.max_y, box.max_z, + box.max_x, box.min_y, box.max_z, + box.min_x, box.min_y, box.max_z, + + box.max_x, box.min_y, box.min_z, + box.min_x, box.min_y, box.min_z, + box.min_x, box.max_y, box.min_z, + + box.max_x, box.min_y, box.min_z, + box.min_x, box.max_y, box.min_z, + box.max_x, box.max_y, box.min_z + ] + end + + def draw_bounding_boxes + glEnableClientState(GL_VERTEX_ARRAY) + glEnableClientState(GL_COLOR_ARRAY) + glEnableClientState(GL_NORMAL_ARRAY) + + _normals = @bounding_boxes[:normals].flatten.pack("f*") + _colors = @bounding_boxes[:colors].flatten.pack("f*") + _vertices_size = @bounding_boxes[:vertices].size + _vertices = @bounding_boxes[:vertices].flatten.pack("f*") + + glVertexPointer(3, GL_FLOAT, 0, _vertices) + glColorPointer(3, GL_FLOAT, 0, _colors) + glNormalPointer(GL_FLOAT, 0, _normals) + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) + glDisable(GL_LIGHTING) + glDrawArrays(GL_TRIANGLES, 0, _vertices_size/3) + glEnable(GL_LIGHTING) + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) + + glDisableClientState(GL_VERTEX_ARRAY) + glDisableClientState(GL_COLOR_ARRAY) + glDisableClientState(GL_NORMAL_ARRAY) + end + + def handleGlError + e = glGetError() + if e != GL_NO_ERROR + $stderr.puts "OpenGL error in: #{gluErrorString(e)} (#{e})\n" + exit + end + end + + def finalize # cleanup + end + end +end \ No newline at end of file diff --git a/lib/states/game_states/game.rb b/lib/states/game_states/game.rb index 3161fe1..0c466d1 100644 --- a/lib/states/game_states/game.rb +++ b/lib/states/game_states/game.rb @@ -4,6 +4,7 @@ class IMICFPS include GLU def setup + @renderer = Renderer.new @terrain = Terrain.new#(size: 170, height: 0) @draw_skydome = true @skydome = Skydome.new(scale: 0.08, backface_culling: false, auto_manage: false) @@ -48,12 +49,10 @@ class IMICFPS LightManager.lights.each(&:draw) @camera.draw - @skydome.draw if @skydome.renderable + @renderer.draw_object(@skydome) if @skydome.renderable glEnable(GL_DEPTH_TEST) - ObjectManager.objects.each do |object| - object.draw if object.visible && object.renderable - end + @renderer.draw end # Draw crosshair diff --git a/lib/states/menu.rb b/lib/states/menu.rb index be06dfe..17835e2 100644 --- a/lib/states/menu.rb +++ b/lib/states/menu.rb @@ -80,7 +80,7 @@ class IMICFPS end def button_up(id) - close if id == Gosu::KbEscape + $window.close if id == Gosu::KbEscape if Gosu::MsLeft @elements.each do |e| next unless e.is_a?(Link) diff --git a/lib/wavefront/model.rb b/lib/wavefront/model.rb index 8570b07..107597c 100644 --- a/lib/wavefront/model.rb +++ b/lib/wavefront/model.rb @@ -12,7 +12,7 @@ class IMICFPS attr_accessor :objects, :materials, :vertices, :texures, :normals, :faces attr_accessor :x, :y, :z, :scale, :game_object - attr_reader :bounding_box + attr_reader :bounding_box, :model_has_texture, :textured_material def initialize(file_path:, game_object: nil) @game_object = game_object @@ -51,55 +51,6 @@ class IMICFPS end end - def draw(x,y,z, scale, back_face_culling) - @x,@y,@z,@scale,@back_face_culling = 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) - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE) - glShadeModel(GL_FLAT) unless o.faces.first[4] - glShadeModel(GL_SMOOTH) if o.faces.first[4] - glEnableClientState(GL_VERTEX_ARRAY) - glEnableClientState(GL_COLOR_ARRAY) - glEnableClientState(GL_NORMAL_ARRAY) - if @model_has_texture - glEnable(GL_TEXTURE_2D) - glBindTexture(GL_TEXTURE_2D, @materials[@textured_material].texture_id) - glEnableClientState(GL_TEXTURE_COORD_ARRAY) - glTexCoordPointer(3, GL_FLOAT, 0, o.flattened_textures) - end - glVertexPointer(4, GL_FLOAT, 0, o.flattened_vertices) - glColorPointer(3, GL_FLOAT, 0, o.flattened_materials) - glNormalPointer(GL_FLOAT, 0, o.flattened_normals) - - glDrawArrays(GL_TRIANGLES, 0, o.flattened_vertices_size/4) - - if $debug - glDisable(GL_LIGHTING) - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) - glPolygonOffset(2, 0.5) - glLineWidth(3) - glDrawArrays(GL_TRIANGLES, 0, o.flattened_vertices_size/4) - glLineWidth(1) - glPolygonOffset(0, 0) - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) - glEnable(GL_LIGHTING) - end - - glDisableClientState(GL_VERTEX_ARRAY) - glDisableClientState(GL_COLOR_ARRAY) - glDisableClientState(GL_NORMAL_ARRAY) - if @model_has_texture - glDisableClientState(GL_TEXTURE_COORD_ARRAY) - # glBindTexture(GL_TEXTURE_2D, 0) - glDisable(GL_TEXTURE_2D) - end - glDisable(GL_CULL_FACE) if back_face_culling - glDisable(GL_COLOR_MATERIAL) - end - $window.number_of_faces+=self.faces.size - end - def update @x, @y, @z = @game_object.x, @game_object.y, @game_object.z @scale = @game_object.scale