OBB 2D + OBB 2D colision
Post by bluatigro on Nov 6th, 2015, 11:18am
this is a try at oriented bonding boxes
error :
- no rect shape
- obb.hit1way() error
i think i made a typo somwere
Code:
dim obb( 37 , 12 )
global corner , axes , org , x , y , pi
global true , false
false = 0
true = not( false )
corner = 0
axes = 8
org = 10
x = 0
y = 1
pi = atn( 1 ) * 4
WindowWidth = DisplayWidth
WimdowHeight = DisplayHeight
global winx , winy
winx = WindowWidth
winy = WindowHeight
nomainwin
open "obb 2d" for graphics as #m
#m "trapclose [quit]"
#m "size 5"
for i = 0 to 36
call obb.fill i , winx / 6 , winy / 2 _
, 50 , 100 , i * 10
next i
call obb.fill 37 , winx - 100 , winy / 2 _
, 50 , 100 , 30
timer 100 , [timer]
wait
[timer]
#m "cls"
for i = 0 to 36
if not( obb.hit( i , 37 ) ) then
call obb.move i , 5 , 0
end if
call obb.show i
next i
call obb.show 37
wait
[quit]
close #m
end
end
function dot( a,b , c,d )
dot = a * c + b * d
end function
sub obb.show no
cx0 = obb( no , corner + x )
cy0 = obb( no , corner + y )
cx1 = obb( no , corner + 2 + x )
cy1 = obb( no , corner + 2 + y )
cx2 = obb( no , corner + 4 + x )
cy2 = obb( no , corner + 4 + y )
cx3 = obb( no , corner + 6 + x )
cy3 = obb( no , corner + 6 + y )
#m "down"
#m "line ";cx0;" ";cy0;" ";cx1;" ";cy1
#m "line ";cx1;" ";cy1;" ";cx2;" ";cy2
#m "line ";cx2;" ";cy2;" ";cx3;" ";cy3
#m "line ";cx3;" ";cy3;" ";cx0;" ";cy0
#m "up"
end sub
function obb.hit1way( this , other )
uit = true
for a = 0 to 1
ax = obb( this , axes + a * 2 + x )
ay = obb( this , axes + a * 2 + y )
cx = obb( other , corner + x )
cy = obb( other , corner + y )
t = dot( ax , ay , cx , cy )
tmin = t
tmax = t
for c = 0 to 3
ax = obb( this , axes + a * 2 + x )
ay = obb( this , axes + a * 2 + y )
cx = obb( other , corner + c * 2 + x )
cy = obb( other , corner + c * 2 + y )
if t < tmin then
tmin = t
else
if t > tmax then
tmax = t
end if
end if
next c
o = obb( this , org + a )
if tmin > 1 + o or tmax < o then
uit = false
end if
next a
obb.hit1way = uit
end function
function obb.hit( a , b )
obb.hit = obb.hit1way( a , b ) _
and obb.hit1way( b , a )
end function
sub obb.move no , dx , dy
for i = 0 to 3
a = obb( no , corner + i * 2 + x )
b = obb( no , corner + i * 2 + y )
a = a + dx
b = b + dy
obb( no , corner + i * 2 + x ) = a
obb( no , corner + i * 2 + y ) = b
next i
call calcAxes no
end sub
sub calcAxes no
cx0 = obb( no , corner + x )
cy0 = obb( no , corner + y )
cx1 = obb( no , corner + 2 + x )
cy1 = obb( no , corner + 2 + y )
cx3 = obb( no , corner + 6 + x )
cy3 = obb( no , corner + 6 + y )
ax0 = cx1 - cx0
ay0 = cy1 - cy0
ax1 = cx3 - cx0
ay1 = cy3 - cy0
l = dot( ax0 , ay0 , ax0 , ay0 ) + 1e-5
ax0 = ax0 / l
ay0 = ay0 / l
o0 = dot( ax0 , ay0 , cx0 , cy0 )
l = dot( ax1 , ay1 , ax1 , ay1 ) + 1e-5
ax1 = ax1 / l
ay1 = ay1 / l
o1 = dot( ax1 , ay1 , cx0 , cy0 )
obb( no , axes + x ) = ax0
obb( no , axes + y ) = ax0
obb( no , axes + 2 + x ) = ax1
obb( no , axes + 2 + y ) = ax1
obb( no , org ) = o0
obb( no , org + 1 ) = o1
end sub
sub obb.fill no , cx , cy , w , h , deg
ax = cos( rad( deg ) )
ay = sin( rad( deg ) )
bx = cos( rad( deg ) )
by = 0-sin( rad( deg ) )
ax = ax * w / 2
ay = ay * w / 2
bx = bx * h / 2
by = by * h / 2
obb( no , corner + x ) = cx - ax - bx
obb( no , corner + y ) = cy - ay - by
obb( no , corner + 2 + x ) = cx + ax - bx
obb( no , corner + 2 + y ) = cy + ay - by
obb( no , corner + 4 + x ) = cx + ax + bx
obb( no , corner + 4 + y ) = cy + ay + by
obb( no , corner + 6 + x ) = cx - ax + bx
obb( no , corner + 6 + y ) = cy - ay + by
call calcAxes no
end sub
function rad( deg )
rad = deg * pi / 180
end function
Re: OBB 2D + OBB 2D colision
Post by bluatigro on Nov 11th, 2015, 09:55am
update :
- shape error fixed
error :
- no colision detected
Code:
dim obb( 37 , 12 )
global corner , axes , org , x , y , pi
global true , false
false = 0
true = not( false )
corner = 0
axes = 8
org = 10
x = 0
y = 1
pi = atn( 1 ) * 4
WindowWidth = DisplayWidth
WindowHeight = DisplayHeight
global winx , winy
winx = WindowWidth
winy = WindowHeight
nomainwin
open "obb 2d" for graphics as #m
#m "trapclose [quit]"
#m "size 5"
for i = 0 to 36
call obb.fill i , winx / 6 , winy / 2 _
, 50 , 100 , i * 10
next i
call obb.fill 37 , winx * 5 / 6 , winy / 2 _
, 50 , 100 , 15
timer 100 , [timer]
wait
[timer]
#m "cls"
for i = 0 to 36
if not( obb.hit( i , 37 ) ) then
call obb.move i , 5 , 0
end if
call obb.show i
next i
call obb.show 37
wait
[quit]
close #m
end
end
function dot( a,b , c,d )
dot = a * c + b * d
end function
sub obb.show no
cx0 = obb( no , corner + x )
cy0 = obb( no , corner + y )
cx1 = obb( no , corner + 2 + x )
cy1 = obb( no , corner + 2 + y )
cx2 = obb( no , corner + 4 + x )
cy2 = obb( no , corner + 4 + y )
cx3 = obb( no , corner + 6 + x )
cy3 = obb( no , corner + 6 + y )
#m "down"
#m "line ";cx0;" ";cy0;" ";cx1;" ";cy1
#m "line ";cx1;" ";cy1;" ";cx2;" ";cy2
#m "line ";cx2;" ";cy2;" ";cx3;" ";cy3
#m "line ";cx3;" ";cy3;" ";cx0;" ";cy0
#m "up"
end sub
function obb.hit1way( this , other )
uit = true
for a = 0 to 1
ax = obb( this , axes + a * 2 + x )
ay = obb( this , axes + a * 2 + y )
cx = obb( other , corner + x )
cy = obb( other , corner + y )
t = dot( ax , ay , cx , cy )
tmin = t
tmax = t
for c = 0 to 3
ax = obb( this , axes + a * 2 + x )
ay = obb( this , axes + a * 2 + y )
cx = obb( other , corner + c * 2 + x )
cy = obb( other , corner + c * 2 + y )
if t < tmin then
tmin = t
else
if t > tmax then
tmax = t
end if
end if
next c
o = obb( this , org + a )
if tmin > 1 + o or tmax < o then
uit = false
end if
next a
obb.hit1way = uit
end function
function obb.hit( a , b )
obb.hit = obb.hit1way( a , b ) _
and obb.hit1way( b , a )
end function
sub obb.move no , dx , dy
for i = 0 to 3
a = obb( no , corner + i * 2 + x )
b = obb( no , corner + i * 2 + y )
a = a + dx
b = b + dy
obb( no , corner + i * 2 + x ) = a
obb( no , corner + i * 2 + y ) = b
next i
call calcAxes no
end sub
sub calcAxes no
cx0 = obb( no , corner + x )
cy0 = obb( no , corner + y )
cx1 = obb( no , corner + 2 + x )
cy1 = obb( no , corner + 2 + y )
cx3 = obb( no , corner + 6 + x )
cy3 = obb( no , corner + 6 + y )
ax0 = cx1 - cx0
ay0 = cy1 - cy0
ax1 = cx3 - cx0
ay1 = cy3 - cy0
l = dot( ax0 , ay0 , ax0 , ay0 ) + 1e-5
ax0 = ax0 / l
ay0 = ay0 / l
o0 = dot( ax0 , ay0 , cx0 , cy0 )
l = dot( ax1 , ay1 , ax1 , ay1 ) + 1e-5
ax1 = ax1 / l
ay1 = ay1 / l
o1 = dot( ax1 , ay1 , cx0 , cy0 )
obb( no , axes + x ) = ax0
obb( no , axes + y ) = ax0
obb( no , axes + 2 + x ) = ax1
obb( no , axes + 2 + y ) = ax1
obb( no , org ) = o0
obb( no , org + 1 ) = o1
end sub
sub obb.fill no , cx , cy , w , h , angle
x1 = w / 2
y1 = h / 2
x2 = 0 - w / 2
y2 = h / 2
x3 = 0 - w / 2
y3 = 0 - h / 2
x4 = w / 2
y4 = 0 - h / 2
call rotate x1 , y1 , angle
call rotate x2 , y2 , angle
call rotate x3 , y3 , angle
call rotate x4 , y4 , angle
obb( no , corner + x ) = cx + x1
obb( no , corner + y ) = cy + y1
obb( no , corner + 2 + x ) = cx + x2
obb( no , corner + 2 + y ) = cy + y2
obb( no , corner + 4 + x ) = cx + x3
obb( no , corner + 4 + y ) = cy + y3
obb( no , corner + 6 + x ) = cx + x4
obb( no , corner + 6 + y ) = cy + y4
call calcAxes no
end sub
function rad( deg )
rad = deg * pi / 180
end function
sub rotate byref k , byref l , deg
s = sin( rad( deg ) )
c = cos( rad( deg ) )
hk = k * c - l * s
hl = k * s + l * c
k = hk
l = hl
end sub
translated from freebasic
Code:
screen 20 , 32 , 2
type t2d
public :
dim as double x , y
declare constructor ( nx as double = 0 , ny as double = 0 )
declare sub fill( nx as double , ny as double )
declare function dot( r as t2d ) as double
declare function squaredLenght() as double
end type
constructor t2d( nx as double , ny as double )
x = nx
y = ny
end constructor
sub t2d.fill( nx as double , ny as double )
x = nx
y = ny
end sub
function t2d.dot( r as t2d ) as double
return x * r.x + y * r.y
end function
function t2d.squaredLenght() as double
return x ^ 2 + y ^ 2
end function
operator + ( a as t2d , b as t2d ) as t2d
return type( a.x + b.x , a.y + b.y )
end operator
operator - ( a as t2d , b as t2d ) as t2d
return type( a.x - b.x , a.y - b.y )
end operator
operator * ( v as t2d , f as double ) as t2d
return type( v.x * f , v.y * f )
end operator
operator / ( v as t2d , f as double ) as t2d
return type( v.x / f , v.y / f )
end operator
const as integer false = 0
const as integer true = not false
const as double pi = atn( 1 ) * 4
function rad( gr as double ) as double
return gr * pi / 180
end function
type obb2d
private :
dim as t2d corner( 4 ) , axis( 2 )
dim as double origin( 2 )
declare function hit1way( other as obb2d ) as integer
declare sub computeAxis()
public :
declare constructor
declare sub fill( cx as double , cy as double _
, w as double , h as double , angle as double )
declare function hit( other as obb2d ) as integer
declare sub move( dx as double , dy as double )
declare sub drawit( kl as integer )
end type
constructor obb2d
end constructor
sub obb2d.fill( cx as double , cy as double _
, w as double , h as double , angle as double )
dim a as t2d , center as t2d
a.fill cos( angle ) , sin( angle )
dim b as t2d
b.fill -sin( angle ) , cos( angle )
center.fill cx , cy
a *= w / 2
b *= h / 2
corner( 0 ) = center - a - b
corner( 1 ) = center + a - b
corner( 2 ) = center + a + b
corner( 3 ) = center - a + b
computeAxis
end sub
function obb2d.hit1way( other as obb2d ) as integer
dim as integer a , c
dim as double t , tMin , tMax
for a = 0 to 1
t = other.corner( 0 ).dot( axis( a ) )
tMin = t
tMax = t
for c = 0 to 3
t = other.corner( c ).dot( axis( a ) )
if t < tMin then
tMin = t
else
if t > tMax then
tMax = t
end if
end if
next c
if ( tMin > 1 + origin( a ) ) or ( tMax < origin( a ) ) then
return false
end if
next a
return true
end function
sub obb2d.computeAxis()
axis( 0 ) = corner( 1 ) - corner( 0 )
axis( 1 ) = corner( 3 ) - corner( 0 )
dim i as integer
for i = 0 to 1
axis( i ) /= axis( i ).squaredLenght()
origin( i ) = corner( 0 ).dot( axis( i ) )
next i
end sub
function obb2d.hit( other as obb2d ) as integer
return hit1way( other ) and other.hit1way( this )
end function
sub obb2d.move( dx as double , dy as double )
dim i as integer , m as t2d
m.fill dx , dy
for i = 0 to 3
corner( i ) += m
next i
computeAxis
end sub
sub obb2d.drawit( kl as integer )
line ( corner( 0 ).x , corner( 0 ).y ) _
-( corner( 1 ).x , corner( 1 ).y ) , kl
line ( corner( 1 ).x , corner( 1 ).y ) _
-( corner( 2 ).x , corner( 2 ).y ) , kl
line ( corner( 2 ).x , corner( 2 ).y ) _
-( corner( 3 ).x , corner( 3 ).y ) , kl
line ( corner( 3 ).x , corner( 3 ).y ) _
-( corner( 0 ).x , corner( 0 ).y ) , kl
end sub
function rainbow( x as double ) as integer
return rgb( sin( x ) * 127 + 128 _
, sin( x + pi * 2 / 3 ) * 127 + 128 _
, sin( x - pi * 2 / 3 ) * 127 + 128 )
end function
dim i as integer
dim a( 20 ) as obb2d
for i = 0 to 20
a( i ).fill 200 , 350 , 100 , 200 , pi/20*i
next i
dim b as obb2d
b.fill 800 , 350 , 100 , 200 , -1
dim in as string
screenset 1 , 0
do
cls
for i = 0 to 20
if not a( i ).hit( b ) then
a( i ).move 1 , 0
end if
next i
for i = 0 to 20
a( i ).drawit rainbow( i * pi / 10 )
next i
b.drawit rgb( 255 , 255 , 255 )
sleep 40
flip
in = inkey
loop while in = ""