Skip to content

Commit 5ae018d

Browse files
committed
reduce OBB memory allocation
1 parent ee9a0e5 commit 5ae018d

1 file changed

Lines changed: 58 additions & 58 deletions

File tree

src/utils/obb.js

Lines changed: 58 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
import 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

58
export 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

Comments
 (0)