Fixed bounding box rendering! fixed AABB collision detection (was a bit weird), misc. tweaks and fixes.

This commit is contained in:
2018-12-09 21:17:12 -06:00
parent a5b2ab7992
commit 7271c0e4a1
9 changed files with 175 additions and 90 deletions

View File

@@ -3,8 +3,8 @@ GEM
specs: specs:
glu (8.2.2) glu (8.2.2)
glu (8.2.2-x86-mingw32) glu (8.2.2-x86-mingw32)
gosu (0.14.0) gosu (0.14.4)
gosu (0.14.0-x86-mingw32) gosu (0.14.4-x86-mingw32)
opengl-bindings (1.6.7) opengl-bindings (1.6.7)
PLATFORMS PLATFORMS
@@ -17,4 +17,4 @@ DEPENDENCIES
opengl-bindings opengl-bindings
BUNDLED WITH BUNDLED WITH
1.16.4 1.16.6

View File

@@ -64,21 +64,25 @@ class IMICFPS
def draw def draw
end end
def update def update
model.update model.update
@delta_time = Gosu.milliseconds @delta_time = Gosu.milliseconds
end end
def debug_color=(color)
@debug_color = color
end
# Do two Axis Aligned Bounding Boxes intersect? # Do two Axis Aligned Bounding Boxes intersect?
def intersect(a, b) def intersect(a, b)
a = a.normalize_bounding_box(a.model.bounding_box) a = a.normalize_bounding_box_with_offset(a.model.bounding_box)
b = b.normalize_bounding_box(b.model.bounding_box) b = b.normalize_bounding_box_with_offset(b.model.bounding_box)
puts "bounding boxes match!" if a == b # puts "bounding boxes match!" if a == b
if (((a.min_x <= b.min_x && b.max_x <= a.max_x) || (b.min_x <= a.min_x && a.min_x <= b.max_x)) && if (a.min_x <= b.max_x && a.max_x >= b.min_x) &&
((a.min_y <= b.min_y && b.max_y <= a.max_y) || (b.min_y <= a.min_y && a.min_y <= b.max_y)) && (a.min_y <= b.max_y && a.max_y >= b.min_y) &&
((a.min_z <= b.min_z && b.max_z <= a.max_z) || (b.min_z <= a.min_z && a.min_z <= b.max_z))) (a.min_z <= b.max_z && a.max_z >= b.min_z)
# 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)
return true return true
else else
return false return false
@@ -86,6 +90,19 @@ class IMICFPS
end end
def normalize_bounding_box(box) def normalize_bounding_box(box)
temp = BoundingBox.new
temp.min_x = box.min_x.to_f*scale
temp.min_y = box.min_y.to_f*scale
temp.min_z = box.min_z.to_f*scale
temp.max_x = box.max_x.to_f*scale
temp.max_y = box.max_y.to_f*scale
temp.max_z = box.max_z.to_f*scale
return temp
end
def normalize_bounding_box_with_offset(box)
temp = BoundingBox.new temp = BoundingBox.new
temp.min_x = box.min_x.to_f*scale+x temp.min_x = box.min_x.to_f*scale+x
temp.min_y = box.min_y.to_f*scale+y temp.min_y = box.min_y.to_f*scale+y
@@ -95,7 +112,6 @@ class IMICFPS
temp.max_y = box.max_y.to_f*scale+y temp.max_y = box.max_y.to_f*scale+y
temp.max_z = box.max_z.to_f*scale+z temp.max_z = box.max_z.to_f*scale+z
# puts "b: #{box}, Temp: #{temp}"
return temp return temp
end end

View File

@@ -36,7 +36,7 @@ class IMICFPS
found = false found = false
if CACHE[@type].is_a?(Hash) if CACHE[@type].is_a?(Hash)
if CACHE[@type][@file_path] if CACHE[@type][@file_path]
@model = CACHE[@type][@file_path].dup # Don't know why, but adding .dup improves performance with Sponza (1 fps -> 20 fps) @model = CACHE[@type][@file_path]#.dup # Don't know why, but adding .dup improves performance with Sponza (1 fps -> 20 fps)
puts "Used cached model for: #{@file_path.split('/').last}" puts "Used cached model for: #{@file_path.split('/').last}"
found = true found = true
end end

View File

@@ -3,9 +3,10 @@ class IMICFPS
include OpenGL include OpenGL
include GLU include GLU
attr_reader :bounding_boxes attr_reader :bounding_boxes, :vertex_count
def initialize def initialize
@bounding_boxes = {normals: [], colors: [], vertices: []} @bounding_boxes = {}
@vertex_count = 0
end end
def handleGlError def handleGlError
@@ -16,15 +17,25 @@ class IMICFPS
end end
end end
def create_bounding_box(object, box, color = nil) def create_bounding_box(object, box, color = nil, mesh_object_id)
color ||= object.debug_color color ||= object.debug_color
if @bounding_boxes[mesh_object_id]
if @bounding_boxes[mesh_object_id][:color] != color
update_mesh_colors(mesh_object_id, color)
return
else
return
end
end
@bounding_boxes[mesh_object_id] = {}
@bounding_boxes[mesh_object_id] = {object: object, box: box, color: color}
box = object.normalize_bounding_box(box) box = object.normalize_bounding_box(box)
@bounding_boxes[:normals] ||= [] update_mesh_colors(mesh_object_id, color)
@bounding_boxes[:colors] ||= []
@bounding_boxes[:vertices] ||= []
@bounding_boxes[:normals] << [ normals = [
0,1,0, 0,1,0,
0,1,0, 0,1,0,
0,1,0, 0,1,0,
@@ -68,45 +79,7 @@ class IMICFPS
-1,0,0, -1,0,0,
-1,0,0 -1,0,0
] ]
@bounding_boxes[:colors] << [ vertices = [
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.max_z,
box.min_x, box.max_y, box.min_z, box.min_x, box.max_y, box.min_z,
box.max_x, box.max_y, box.min_z, box.max_x, box.max_y, box.min_z,
@@ -155,25 +128,83 @@ class IMICFPS
box.min_x, box.max_y, box.min_z, box.min_x, box.max_y, box.min_z,
box.max_x, box.max_y, box.min_z box.max_x, box.max_y, box.min_z
] ]
@vertex_count+=vertices.size
@bounding_boxes[mesh_object_id][:vertices_size] = vertices.size
@bounding_boxes[mesh_object_id][:vertices] = vertices.pack("f*")
@bounding_boxes[mesh_object_id][:normals] = normals.pack("f*")
end
def update_mesh_colors(mesh_object_id, color)
@bounding_boxes[mesh_object_id][: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*")
@bounding_boxes[mesh_object_id][:color] = color
end end
def draw_bounding_boxes def draw_bounding_boxes
@bounding_boxes.each do |key, bounding_box|
glPushMatrix
glTranslatef(bounding_box[:object].x, bounding_box[:object].y, bounding_box[:object].z)
draw_bounding_box(bounding_box)
glPopMatrix
found = ObjectManager.objects.detect { |o| o == bounding_box[:object] }
@bounding_boxes.delete(key) unless found
end
end
def draw_bounding_box(bounding_box)
glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_COLOR_ARRAY) glEnableClientState(GL_COLOR_ARRAY)
glEnableClientState(GL_NORMAL_ARRAY) glEnableClientState(GL_NORMAL_ARRAY)
_normals = @bounding_boxes[:normals].flatten.pack("f*") glVertexPointer(3, GL_FLOAT, 0, bounding_box[:vertices])
_colors = @bounding_boxes[:colors].flatten.pack("f*") glColorPointer(3, GL_FLOAT, 0, bounding_box[:colors])
_vertices_size = @bounding_boxes[:vertices].size glNormalPointer(GL_FLOAT, 0, bounding_box[:normals])
_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) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
glDisable(GL_LIGHTING) glDisable(GL_LIGHTING)
glDrawArrays(GL_TRIANGLES, 0, _vertices_size/3) glDrawArrays(GL_TRIANGLES, 0, bounding_box[:vertices_size]/3)
glEnable(GL_LIGHTING) glEnable(GL_LIGHTING)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
@@ -182,4 +213,4 @@ class IMICFPS
glDisableClientState(GL_NORMAL_ARRAY) glDisableClientState(GL_NORMAL_ARRAY)
end end
end end
end end

View File

@@ -19,9 +19,6 @@ class IMICFPS
glEnable(GL_NORMALIZE) glEnable(GL_NORMALIZE)
glPushMatrix 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) glTranslatef(object.x, object.y, object.z)
glRotatef(object.x_rotation,1.0, 0, 0) glRotatef(object.x_rotation,1.0, 0, 0)
@@ -59,9 +56,7 @@ class IMICFPS
glColorPointer(3, GL_FLOAT, 0, o.flattened_materials) glColorPointer(3, GL_FLOAT, 0, o.flattened_materials)
glNormalPointer(GL_FLOAT, 0, o.flattened_normals) glNormalPointer(GL_FLOAT, 0, o.flattened_normals)
glDrawArrays(GL_TRIANGLES, 0, o.flattened_vertices_size/4) if $debug # This is kinda expensive
if $debug
glDisable(GL_LIGHTING) glDisable(GL_LIGHTING)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
glPolygonOffset(2, 0.5) glPolygonOffset(2, 0.5)
@@ -71,6 +66,9 @@ class IMICFPS
glPolygonOffset(0, 0) glPolygonOffset(0, 0)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
glEnable(GL_LIGHTING) glEnable(GL_LIGHTING)
glDrawArrays(GL_TRIANGLES, 0, o.flattened_vertices_size/4)
else
glDrawArrays(GL_TRIANGLES, 0, o.flattened_vertices_size/4)
end end
glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_VERTEX_ARRAY)

View File

@@ -11,16 +11,20 @@ class IMICFPS
end end
def draw def draw
@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| ObjectManager.objects.each do |object|
if object.visible && object.renderable if object.visible && object.renderable
# Render bounding boxes before transformation is applied
@bounding_box_renderer.create_bounding_box(object, object.model.bounding_box, object.debug_color, object.object_id) if $debug
object.model.objects.each {|o| @bounding_box_renderer.create_bounding_box(object, o.bounding_box, o.debug_color, o.object_id)} if $debug
@opengl_renderer.draw_object(object) @opengl_renderer.draw_object(object)
end end
end end
@bounding_box_renderer.draw_bounding_boxes if $debug
$window.number_of_faces+=$window.number_of_faces if $debug
$window.number_of_faces+=@bounding_box_renderer.vertex_count/3 if $debug
# @bounding_box_renderer.bounding_boxes.clear
end end
def handleGlError def handleGlError
@@ -34,4 +38,4 @@ class IMICFPS
def finalize # cleanup def finalize # cleanup
end end
end end
end end

View File

@@ -100,15 +100,25 @@ eos
end end
@text.text = string @text.text = string
# ObjectManager.objects.each do |object| ObjectManager.objects.each do |object|
# ObjectManager.objects.each do |b| ObjectManager.objects.each do |b|
# next if b == object next if b == object
# if object.intersect(object, b) next if object.is_a?(Terrain)
# # puts "#{object} is intersecting #{b}" next if b.is_a?(Terrain)
# end
# end if object.intersect(object, b)
# object.update object.debug_color = Color.new(1.0,0.0,0.0)
# end b.debug_color = Color.new(1.0,0.0,0.0)
# ObjectManager.objects.delete(object)
# puts "#{object} is intersecting #{b}" if object.is_a?(Player)
else
object.debug_color = Color.new(0,1,0)
b.debug_color = Color.new(0,1,0)
end
end
end
ObjectManager.objects.each(&:update) ObjectManager.objects.each(&:update)
@skydome.update if @skydome.renderable @skydome.update if @skydome.renderable

View File

@@ -13,6 +13,7 @@ class IMICFPS
attr_accessor :objects, :materials, :vertices, :texures, :normals, :faces attr_accessor :objects, :materials, :vertices, :texures, :normals, :faces
attr_accessor :x, :y, :z, :scale, :game_object attr_accessor :x, :y, :z, :scale, :game_object
attr_reader :bounding_box, :model_has_texture, :textured_material attr_reader :bounding_box, :model_has_texture, :textured_material
attr_reader :normals_buffer, :colors_buffer, :vertices_buffer
def initialize(file_path:, game_object: nil) def initialize(file_path:, game_object: nil)
@game_object = game_object @game_object = game_object
@@ -31,11 +32,27 @@ class IMICFPS
@faces = [] @faces = []
@smoothing= 0 @smoothing= 0
# Allocate buffers for future use
@normals_buffer, @colors_buffer, @vertices_buffer = nil
buffer = " " * 4
glGenBuffers(1, buffer)
@normals_buffer = buffer.unpack('L2').first
buffer = " " * 4
glGenBuffers(1, buffer)
@colors_buffer = buffer.unpack('L2').first
buffer = " " * 4
glGenBuffers(1, buffer)
@vertices_buffer = buffer.unpack('L2').first
@bounding_box = BoundingBox.new(0,0,0, 0,0,0) @bounding_box = BoundingBox.new(0,0,0, 0,0,0)
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond) start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
parse parse
puts "#{@file_path.split('/').last} took #{((Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)-start_time)/1000.0).round(2)} seconds to parse" puts "#{@file_path.split('/').last} took #{((Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)-start_time)/1000.0).round(2)} seconds to parse"
# populate_buffers
face_count = 0 face_count = 0
@objects.each {|o| face_count+=o.faces.size} @objects.each {|o| face_count+=o.faces.size}
@objects.each_with_index do |o, i| @objects.each_with_index do |o, i|
@@ -51,6 +68,15 @@ class IMICFPS
end end
end end
def populate_buffers
glBindBuffer(GL_ARRAY_BUFFER, @normals_buffer)
glBufferData(GL_ARRAY_BUFFER, @vertices.size, @vertices.flatten.pack("f*"), GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, @colors_buffer)
glBindBuffer(GL_ARRAY_BUFFER, @vertices_buffer)
end
def update def update
@x, @y, @z = @game_object.x, @game_object.y, @game_object.z @x, @y, @z = @game_object.x, @game_object.y, @game_object.z
@scale = @game_object.scale @scale = @game_object.scale

View File

@@ -38,7 +38,7 @@ class IMICFPS
def at_same_position? def at_same_position?
if @x == @parent.x if @x == @parent.x
if @x == @parent.x if @y == @parent.y
if @z == @parent.z if @z == @parent.z
true true
end end