Skip to content

Commit

Permalink
fixed reindex rounding error
Browse files Browse the repository at this point in the history
  • Loading branch information
shawn42 committed Jan 23, 2012
1 parent 5fcee27 commit e7dd630
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Gemfile
@@ -1,3 +1,3 @@
source "http://rubygems.org"
gemspec
gem 'perftools.rb', :git => 'git://github.com/bearded/perftools.rb.git', :branch => 'perftools-1.8'
# gem 'perftools.rb', :git => 'git://github.com/bearded/perftools.rb.git', :branch => 'perftools-1.8'
9 changes: 8 additions & 1 deletion lib/gamebox/aabb_arbiter.rb
Expand Up @@ -64,10 +64,16 @@ def find_collisions

collisions = {}

# aabb_tree.each do |actor|
# puts "#{actor.class} #{actor.bb}"
# end
puts "#"*80
puts aabb_tree.instance_variable_get('@tree')
collidable_actors.each do |first|
if first.is? :collidable
# TODO better method name (or return an Enumerator)
aabb_tree.neighbors_of(first) do |second|
puts "FOUND neighbors_of #{first.class}, #{second.class}" unless first == second
if second.is? :collidable
if first != second &&
interested_in_collision_of?(first.actor_type, second.actor_type) &&
Expand All @@ -88,6 +94,7 @@ def find_collisions
unique_collisions << [first,second]
end
end
puts "found #{unique_collisions.size} uniqs" if unique_collisions.size > 0
run_callbacks unique_collisions
aabb_tree.reset
end
Expand Down Expand Up @@ -146,7 +153,7 @@ def collide_polygon_polygon?(object, other)
potential_sep_axis =
(object.cw_world_edge_normals | other.cw_world_edge_normals).uniq
potential_sep_axis.each do |axis|
return false unless project_and_detect(axis, object, other)
return false unless project_and_detect(axis, object, other)
end
else
return false
Expand Down
81 changes: 43 additions & 38 deletions lib/gamebox/aabb_tree.rb
Expand Up @@ -56,20 +56,21 @@ def remove(item)
end

def reindex(item)
leaf = @items[item.object_id]
if leaf && leaf.leaf?
node = @items[item.object_id]
if node && node.leaf?
new_bb = item.bb #calculate_bb(item)
unless leaf.bb.contain? new_bb

unless node.bb.contain? new_bb
# use velocity vector to extrap
# 10% bigger
horizontal_growth = new_bb.w + 0.1
vertical_growth = new_bb.h + 0.1
leaf.bb[0,4] = new_bb.x - horizontal_growth, new_bb.y - vertical_growth,
new_bb.w + 2*horizontal_growth, new_bb.h + 2*vertical_growth

@root = @root.remove_subtree leaf
insert_leaf leaf
horizontal_growth = (new_bb.w * 0.1).round
vertical_growth = (new_bb.h * 0.1).round
node.bb[0] = new_bb.x - horizontal_growth
node.bb[1] = new_bb.y - vertical_growth
node.bb[2] = new_bb.w + 2*horizontal_growth
node.bb[3] = new_bb.h + 2*vertical_growth

@root = @root.remove_subtree node
insert_leaf node
end
end
end
Expand All @@ -88,36 +89,27 @@ def calculate_bb(item)
end
w ||= 2
h ||= 2
hh = h / 2
hw = h / 2
# 10% bigger
horizontal_growth = w + 0.05
vertical_growth = h + 0.05
# Rect.new item.x - hh - horizontal_growth, item.y - hh - vertical_growth,
# w + 2*horizontal_growth, h + 2*vertical_growth

horizontal_growth = w + 0.05
vertical_growth = h + 0.05
Rect.new item.x - horizontal_growth, item.y - vertical_growth,

horizontal_growth = (w * 0.05).round
vertical_growth = (h * 0.05).round

Rect.new item.x - horizontal_growth, item.y - vertical_growth,
w + 2*horizontal_growth, h + 2*vertical_growth
end
end

def neighbors_of(item, &blk)
leaf = @items[item.object_id]
return unless leaf
# if leaf.parent
# leaf.parent.query_subtree leaf.bb, &blk
# else
query calculate_bb(item), &blk
# end
# @items.keys.each do |item|
# blk.call item
# end
@root.query_subtree calculate_bb(item), &blk
end

def valid?
@root.contains_children?
end

class Node
attr_accessor :bb, :a, :b, :parent
attr_accessor :bb, :a, :b, :parent, :object

def initialize(parent, object, bb)
@parent = parent
Expand Down Expand Up @@ -165,6 +157,7 @@ def union_bb_area(bb, rect)
end

def union_bb(bb, rect)
# TODO can this be changed to actually update bb?
rleft = bb.left
rtop = bb.top
rright = bb.right
Expand All @@ -176,21 +169,19 @@ def union_bb(bb, rect)
rright = max(rright, r2.right)
rbottom = max(rbottom, r2.bottom)

Rect.new rleft, rtop, rright - rleft, rbottom - rtop
Rect.new(rleft, rtop, rright - rleft, rbottom - rtop)
end

def insert_subtree(leaf)
if leaf?
# node new
new_node = Node.new nil, nil, union_bb(@bb, leaf.bb) #@bb.union(leaf.bb)
new_node = Node.new nil, nil, union_bb(@bb, leaf.bb)
new_node.a = self
new_node.b = leaf
return new_node
else
cost_a = @b.bb.area + union_bb_area(@a.bb, leaf.bb) # @a.bb.union(leaf.bb).area
cost_b = @a.bb.area + union_bb_area(@b.bb, leaf.bb) # @b.bb.union(leaf.bb).area
# cost_a = @b.bb.area + @a.bb.union(leaf.bb).area
# cost_b = @a.bb.area + @b.bb.union(leaf.bb).area
cost_a = @b.bb.area + union_bb_area(@a.bb, leaf.bb)
cost_b = @a.bb.area + union_bb_area(@b.bb, leaf.bb)

if cost_a == cost_b
# tie breaker
Expand All @@ -204,6 +195,7 @@ def insert_subtree(leaf)
end

@bb = union_bb(@bb, leaf.bb)
# TODO expand_to_include leaf.bb
return self
end
end
Expand Down Expand Up @@ -266,6 +258,17 @@ def query_subtree(search_bb, &blk)
end
end

def contains_children?
if leaf?
true
else
@bb.contain?(a.bb) &&
@bb.contain?(b.bb) &&
@a.contains_children? &&
@b.contains_children?
end
end

def to_s
if leaf?
"""
Expand All @@ -277,14 +280,16 @@ def to_s
else
"""
Container #{object_id}
UnionedBB: #{union_bb(@a.bb, @b.bb)}
ACollide?: #{@bb.collide_rect?(@a.bb)}
BCollide?: #{@bb.collide_rect?(@b.bb)}
BB: #{@bb}
A: #{@a}
B: #{@b}
Parent: #{@parent.object_id}
"""
end
end

end

end
2 changes: 1 addition & 1 deletion lib/gamebox/spatial_tree_stagehand.rb
Expand Up @@ -2,7 +2,7 @@

class SpatialTreeStagehand < Stagehand
extend Forwardable
def_delegators :@tree, :neighbors_of, :calculate_bb, :to_s
def_delegators :@tree, :neighbors_of, :calculate_bb, :to_s, :each

attr_reader :moved_items

Expand Down
15 changes: 15 additions & 0 deletions spec/aabb_tree_spec.rb
Expand Up @@ -17,6 +17,7 @@
subject.insert two
subject.insert three
subject.size.should == 3
subject.valid?.should be_true
# puts subject.to_s

subject.remove one
Expand All @@ -43,9 +44,12 @@
found_items << item
end
found_items.should == [two, three]
subject.valid?.should be_true

subject.valid?.should be_true
two.bb = Rect.new -10, -10, 1, 1
subject.reindex two
subject.valid?.should be_true
found_items = []
subject.query [1,1,10, 10] do |item|
found_items << item
Expand All @@ -57,6 +61,17 @@
them << item
end
them.map(&:object_id).size.should == 3
subject.valid?.should be_true

them = []
two.bb = Rect.new 5, 8, 6, 10
subject.reindex two
found_items = []
subject.neighbors_of two do |item|
found_items << item
end
found_items.should =~ [three, two]
subject.valid?.should be_true

# require 'perftools'

Expand Down

0 comments on commit e7dd630

Please sign in to comment.