diff --git a/i-mic-fps.rb b/i-mic-fps.rb index 77b43ce..48bbc20 100644 --- a/i-mic-fps.rb +++ b/i-mic-fps.rb @@ -44,7 +44,10 @@ $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/renderer/opengl_renderer" +require_relative "lib/renderer/bounding_box_renderer" require_relative "lib/states/game_state" require_relative "lib/states/game_states/loading_state" diff --git a/lib/objects/player.rb b/lib/objects/player.rb index 813ede0..abae428 100644 --- a/lib/objects/player.rb +++ b/lib/objects/player.rb @@ -40,6 +40,7 @@ class IMICFPS _width = (@name_image.width/@devisor)/2 _y = 2#normalize_bounding_box(model.bounding_box).max_y+0.05 glPushMatrix + glRotatef(180, 0, 1, 0) glDisable(GL_LIGHTING) glEnable(GL_COLOR_MATERIAL) glEnable(GL_TEXTURE_2D) diff --git a/lib/renderer/bounding_box_renderer.rb b/lib/renderer/bounding_box_renderer.rb new file mode 100644 index 0000000..2422493 --- /dev/null +++ b/lib/renderer/bounding_box_renderer.rb @@ -0,0 +1,185 @@ +class IMICFPS + class BoundingBoxRenderer + include OpenGL + include GLU + + attr_reader :bounding_boxes + def initialize + @bounding_boxes = {normals: [], colors: [], vertices: []} + end + + def handleGlError + e = glGetError() + if e != GL_NO_ERROR + $stderr.puts "OpenGL error in: #{gluErrorString(e)} (#{e})\n" + exit + end + 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 + end +end \ No newline at end of file diff --git a/lib/renderer/opengl_renderer.rb b/lib/renderer/opengl_renderer.rb new file mode 100644 index 0000000..2179535 --- /dev/null +++ b/lib/renderer/opengl_renderer.rb @@ -0,0 +1,91 @@ +class IMICFPS + class OpenGLRenderer + include OpenGL + include GLU + + def initialize + end + + def handleGlError + e = glGetError() + if e != GL_NO_ERROR + $stderr.puts "OpenGL error in: #{gluErrorString(e)} (#{e})\n" + exit + 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 + + handleGlError + + glPopMatrix + handleGlError + end + + def draw_mesh(model) + 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 + end +end \ No newline at end of file diff --git a/lib/renderer/renderer.rb b/lib/renderer/renderer.rb index 616ca38..249cccd 100644 --- a/lib/renderer/renderer.rb +++ b/lib/renderer/renderer.rb @@ -3,261 +3,24 @@ class IMICFPS include OpenGL include GLU + attr_reader :opengl_renderer, :bounding_box_renderer + def initialize - @bounding_boxes = {normals: [], colors: [], vertices: []} + @bounding_box_renderer = BoundingBoxRenderer.new + @opengl_renderer = OpenGLRenderer.new end def draw - i = 0 - draw_bounding_boxes if $debug - $window.number_of_faces+=@bounding_boxes[:vertices].size/3 if $debug - @bounding_boxes.clear + @bounding_box_renderer.draw_bounding_boxes if $debug + $window.number_of_faces+=@bounding_box_renderer.bounding_boxes[:vertices].size/3 if $debug + @bounding_box_renderer.bounding_boxes.clear + + ObjectManager.objects.each do |object| if object.visible && object.renderable - draw_object(object) - i+=1 + @opengl_renderer.draw_object(object) 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 diff --git a/lib/states/game_states/game.rb b/lib/states/game_states/game.rb index 0c466d1..0d51c74 100644 --- a/lib/states/game_states/game.rb +++ b/lib/states/game_states/game.rb @@ -49,7 +49,7 @@ class IMICFPS LightManager.lights.each(&:draw) @camera.draw - @renderer.draw_object(@skydome) if @skydome.renderable + @renderer.opengl_renderer.draw_object(@skydome) if @skydome.renderable glEnable(GL_DEPTH_TEST) @renderer.draw