11import Vector from './vector' ;
22
3- const ZERO_AXES = [ [ 1 , 0 ] , [ 0 , 1 ] ] ; // re-use single allocation of axes for 0-angle
3+ // single-allocation, reusable objects
4+ const ZERO_AXES = [ [ 1 , 0 ] , [ 0 , 1 ] ] ;
5+ const proj_a = [ ] , proj_b = [ ] ;
6+ let d0 , d1 , d2 , d3 ;
47
58export default class OBB {
69
710 constructor ( x , y , a , w , h ) {
8- this . dimension = [ w , h ] ;
11+ this . dimension = [ w / 2 , h / 2 ] ; // store half-dimension as that's what's needed in calculations below
912 this . angle = a ;
1013 this . centroid = [ x , y ] ;
1114 this . quad = null ;
12- this . axes = null ;
15+ this . axis_0 = null ;
16+ this . axis_1 = null ;
1317
1418 this . update ( ) ;
1519 }
@@ -27,97 +31,93 @@ export default class OBB {
2731 getExtent ( ) {
2832 // special handling to skip calculations for 0-angle
2933 if ( this . angle === 0 ) {
30- return [ this . quad [ 0 ] [ 0 ] , this . quad [ 0 ] [ 1 ] , this . quad [ 2 ] [ 0 ] , this . quad [ 2 ] [ 1 ] ] ;
34+ return [ this . quad [ 0 ] , this . quad [ 1 ] , this . quad [ 4 ] , this . quad [ 5 ] ] ;
3135 }
3236
33- let aabb = [ Infinity , Infinity , - Infinity , - Infinity ] ;
34-
35- for ( let i = 0 ; i < 4 ; ++ i ) {
36- aabb [ 0 ] = Math . min ( this . quad [ i ] [ 0 ] , aabb [ 0 ] ) ;
37- aabb [ 1 ] = Math . min ( this . quad [ i ] [ 1 ] , aabb [ 1 ] ) ;
38- aabb [ 2 ] = Math . max ( this . quad [ i ] [ 0 ] , aabb [ 2 ] ) ;
39- aabb [ 3 ] = Math . max ( this . quad [ i ] [ 1 ] , aabb [ 3 ] ) ;
40- }
37+ let aabb = [
38+ Math . min ( this . quad [ 0 ] , this . quad [ 2 ] , this . quad [ 4 ] , this . quad [ 6 ] ) ,
39+ Math . min ( this . quad [ 1 ] , this . quad [ 3 ] , this . quad [ 5 ] , this . quad [ 7 ] ) ,
40+ Math . max ( this . quad [ 0 ] , this . quad [ 2 ] , this . quad [ 4 ] , this . quad [ 6 ] ) ,
41+ Math . max ( this . quad [ 1 ] , this . quad [ 3 ] , this . quad [ 5 ] , this . quad [ 7 ] )
42+ ] ;
4143
4244 return aabb ;
4345 }
4446
4547 perpAxes ( ) {
46- this . axes = [
47- // Vector.normalize(Vector.sub(this.quad[2], this.quad[3])),
48- // Vector.normalize(Vector.sub(this.quad[2], this.quad[1]))
49- Vector . normalize ( [ this . quad [ 2 ] [ 0 ] - this . quad [ 1 ] [ 0 ] , this . quad [ 2 ] [ 1 ] - this . quad [ 1 ] [ 1 ] ] ) ,
50- Vector . normalize ( [ this . quad [ 2 ] [ 0 ] - this . quad [ 1 ] [ 0 ] , this . quad [ 2 ] [ 1 ] - this . quad [ 1 ] [ 1 ] ] )
51- ] ;
48+ this . axis_0 = Vector . normalize ( [ this . quad [ 4 ] - this . quad [ 2 ] , this . quad [ 5 ] - this . quad [ 3 ] ] ) ;
49+ this . axis_1 = Vector . normalize ( [ this . quad [ 4 ] - this . quad [ 2 ] , this . quad [ 5 ] - this . quad [ 3 ] ] ) ;
5250 }
5351
5452 update ( ) {
5553 // special handling to skip calculations for 0-angle
5654 if ( this . angle === 0 ) {
5755 const c = this . centroid ;
58- const w2 = this . dimension [ 0 ] / 2 ;
59- const h2 = this . dimension [ 1 ] / 2 ;
56+ const w2 = this . dimension [ 0 ] ;
57+ const h2 = this . dimension [ 1 ] ;
58+
6059 this . quad = [
61- [ c [ 0 ] - w2 , c [ 1 ] - h2 ] , // lower-left
62- [ c [ 0 ] + w2 , c [ 1 ] - h2 ] , // lower-right
63- [ c [ 0 ] + w2 , c [ 1 ] + h2 ] , // upper-right
64- [ c [ 0 ] - w2 , c [ 1 ] + h2 ] // upper-left
60+ c [ 0 ] - w2 , c [ 1 ] - h2 , // lower-left
61+ c [ 0 ] + w2 , c [ 1 ] - h2 , // lower-right
62+ c [ 0 ] + w2 , c [ 1 ] + h2 , // upper-right
63+ c [ 0 ] - w2 , c [ 1 ] + h2 // upper-left
6564 ] ;
66- this . axes = ZERO_AXES ;
65+
66+ this . axis_0 = ZERO_AXES [ 0 ] ;
67+ this . axis_1 = ZERO_AXES [ 1 ] ;
6768 }
6869 // calculate axes and enclosing quad
6970 else {
70- let x = [ Math . cos ( this . angle ) , Math . sin ( this . angle ) ] ;
71- let y = [ - Math . sin ( this . angle ) , Math . cos ( this . angle ) ] ;
71+ let x0 = Math . cos ( this . angle ) * this . dimension [ 0 ] ;
72+ let x1 = Math . sin ( this . angle ) * this . dimension [ 0 ] ;
7273
73- x = Vector . mult ( x , this . dimension [ 0 ] / 2.0 ) ;
74- y = Vector . mult ( y , this . dimension [ 1 ] / 2.0 ) ;
74+ let y0 = - Math . sin ( this . angle ) * this . dimension [ 1 ] ;
75+ let y1 = Math . cos ( this . angle ) * this . dimension [ 1 ] ;
7576
77+ const c = this . centroid ;
7678 this . quad = [
77- // Vector.sub(Vector.sub(this.centroid, x), y), // lower-left
78- // Vector.sub(Vector.add(this.centroid, x), y), // lower-right
79- // Vector.add(Vector.add(this.centroid, x), y), // upper-right
80- // Vector.add(Vector.sub(this.centroid, x), y) // upper-left
81- [ this . centroid [ 0 ] - x [ 0 ] - y [ 0 ] , this . centroid [ 1 ] - x [ 1 ] - y [ 1 ] ] , // lower-left
82- [ this . centroid [ 0 ] + x [ 0 ] - y [ 0 ] , this . centroid [ 1 ] + x [ 1 ] - y [ 1 ] ] , // lower-right
83- [ this . centroid [ 0 ] + x [ 0 ] + y [ 0 ] , this . centroid [ 1 ] + x [ 1 ] + y [ 1 ] ] , // upper-right
84- [ this . centroid [ 0 ] - x [ 0 ] + y [ 0 ] , this . centroid [ 1 ] - x [ 1 ] + y [ 1 ] ] // upper-left
79+ c [ 0 ] - x0 - y0 , c [ 1 ] - x1 - y1 , // lower-left
80+ c [ 0 ] + x0 - y0 , c [ 1 ] + x1 - y1 , // lower-right
81+ c [ 0 ] + x0 + y0 , c [ 1 ] + x1 + y1 , // upper-right
82+ c [ 0 ] - x0 + y0 , c [ 1 ] - x1 + y1 // upper-left
8583 ] ;
8684
8785 this . perpAxes ( ) ;
8886 }
8987 }
9088
91- static projectToAxis ( obb , axis ) {
92- let min = Infinity ;
93- let max = - Infinity ;
94-
95- let quad = obb . quad ;
96-
89+ static projectToAxis ( obb , axis , proj ) {
9790 // for each axis, project obb quad to it and find min and max values
98- for ( let i = 0 ; i < 4 ; ++ i ) {
99- let d = Vector . dot ( quad [ i ] , axis ) ;
100- min = Math . min ( min , d ) ;
101- max = Math . max ( max , d ) ;
102- }
103-
104- return [ min , max ] ;
91+ let quad = obb . quad ;
92+ d0 = quad [ 0 ] * axis [ 0 ] + quad [ 1 ] * axis [ 1 ] ;
93+ d1 = quad [ 2 ] * axis [ 0 ] + quad [ 3 ] * axis [ 1 ] ;
94+ d2 = quad [ 4 ] * axis [ 0 ] + quad [ 5 ] * axis [ 1 ] ;
95+ d3 = quad [ 6 ] * axis [ 0 ] + quad [ 7 ] * axis [ 1 ] ;
96+
97+ proj [ 0 ] = Math . min ( d0 , d1 , d2 , d3 ) ;
98+ proj [ 1 ] = Math . max ( d0 , d1 , d2 , d3 ) ;
99+ return proj ;
105100 }
106101
107- static axisCollide ( obb_a , obb_b , axes ) {
108- for ( let i = 0 ; i < 2 ; ++ i ) {
109- let a_proj = OBB . projectToAxis ( obb_a , axes [ i ] ) ;
110- let b_proj = OBB . projectToAxis ( obb_b , axes [ i ] ) ;
102+ static axisCollide ( obb_a , obb_b , axis_0 , axis_1 ) {
103+ OBB . projectToAxis ( obb_a , axis_0 , proj_a ) ;
104+ OBB . projectToAxis ( obb_b , axis_0 , proj_b ) ;
105+ if ( proj_b [ 0 ] > proj_a [ 1 ] || proj_b [ 1 ] < proj_a [ 0 ] ) {
106+ return false ;
107+ }
111108
112- if ( b_proj [ 0 ] > a_proj [ 1 ] || b_proj [ 1 ] < a_proj [ 0 ] ) {
113- return false ;
114- }
109+ OBB . projectToAxis ( obb_a , axis_1 , proj_a ) ;
110+ OBB . projectToAxis ( obb_b , axis_1 , proj_b ) ;
111+ if ( proj_b [ 0 ] > proj_a [ 1 ] || proj_b [ 1 ] < proj_a [ 0 ] ) {
112+ return false ;
115113 }
114+
116115 return true ;
117116 }
118117
119118 static intersect ( obb_a , obb_b ) {
120- return OBB . axisCollide ( obb_a , obb_b , obb_a . axes ) && OBB . axisCollide ( obb_a , obb_b , obb_b . axes ) ;
119+ return OBB . axisCollide ( obb_a , obb_b , obb_a . axis_0 , obb_a . axis_1 ) &&
120+ OBB . axisCollide ( obb_a , obb_b , obb_b . axis_0 , obb_b . axis_1 ) ;
121121 }
122122
123123}
0 commit comments