Skip to content

Commit

Permalink
Cache and don't re-create transformed hull points
Browse files Browse the repository at this point in the history
  • Loading branch information
adroitwhiz committed Jan 30, 2020
1 parent b1274d5 commit a24929a
Showing 1 changed file with 39 additions and 13 deletions.
52 changes: 39 additions & 13 deletions src/Drawable.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,19 @@ class Drawable {
this._convexHullPoints = null;
this._convexHullDirty = true;

// Create one Rectangle object each for the bounds obtained from getBounds, getBoundsForBubble, and getAABB.
// These are what get returned when get(Fast)Bounds is called without a "result" rectangle.
// Creating these rectangles per drawable instead of per get(Fast)Bounds call reduces GC.
this._AABB = new Rectangle();
this._preciseBounds = new Rectangle();
this._boundsForBubble = new Rectangle();

// The precise bounding box will be from the transformed convex hull points,
// so initialize the array of transformed hull points in setConvexHullPoints.
// Initializing it once per convex hull recalculation avoids unnecessary creation of twgl.v3 objects.
this._transformedHullPoints = null;
this._transformedHullDirty = true;

this._skinWasAltered = this._skinWasAltered.bind(this);
}

Expand All @@ -120,6 +133,7 @@ class Drawable {
setTransformDirty () {
this._transformDirty = true;
this._inverseTransformDirty = true;
this._transformedHullDirty = true;
}

/**
Expand Down Expand Up @@ -447,6 +461,14 @@ class Drawable {
setConvexHullPoints (points) {
this._convexHullPoints = points;
this._convexHullDirty = false;

// Re-create the "transformed hull points" array.
// We only do this when the hull points change to avoid unnecessary allocations and GC.
this._transformedHullPoints = [];
for (let i = 0; i < points.length; i++) {
this._transformedHullPoints.push(twgl.v3.create());
}
this._transformedHullDirty = true;
}

/**
Expand Down Expand Up @@ -520,7 +542,7 @@ class Drawable {
}
const transformedHullPoints = this._getTransformedHullPoints();
// Search through transformed points to generate box on axes.
result = result || new Rectangle();
result = result || this._preciseBounds;
result.initFromPointsAABB(transformedHullPoints);
return result;
}
Expand All @@ -544,7 +566,7 @@ class Drawable {
const maxY = Math.max.apply(null, transformedHullPoints.map(p => p[1]));
const filteredHullPoints = transformedHullPoints.filter(p => p[1] > maxY - slice);
// Search through filtered points to generate box on axes.
result = result || new Rectangle();
result = result || this._boundsForBubble;
result.initFromPointsAABB(filteredHullPoints);
return result;
}
Expand All @@ -564,7 +586,7 @@ class Drawable {
this._calculateTransform();
}
const tm = this._uniforms.u_modelMatrix;
result = result || new Rectangle();
result = result || this._AABB;
result.initFromModelMatrix(tm);
return result;
}
Expand All @@ -591,23 +613,27 @@ class Drawable {
* @private
*/
_getTransformedHullPoints () {
if (!this._transformedHullDirty) {
return this._transformedHullPoints;
}

const projection = twgl.m4.ortho(-1, 1, -1, 1, -1, 1);
const skinSize = this.skin.size;
const halfXPixel = 1 / skinSize[0] / 2;
const halfYPixel = 1 / skinSize[1] / 2;
const tm = twgl.m4.multiply(this._uniforms.u_modelMatrix, projection);
const transformedHullPoints = [];
for (let i = 0; i < this._convexHullPoints.length; i++) {
const point = this._convexHullPoints[i];
const glPoint = twgl.v3.create(
0.5 + (-point[0] / skinSize[0]) - halfXPixel,
(point[1] / skinSize[1]) - 0.5 + halfYPixel,
0
);
twgl.m4.transformPoint(tm, glPoint, glPoint);
transformedHullPoints.push(glPoint);
}
return transformedHullPoints;
const dstPoint = this._transformedHullPoints[i];

dstPoint[0] = 0.5 + (-point[0] / skinSize[0]) - halfXPixel;
dstPoint[1] = (point[1] / skinSize[1]) - 0.5 + halfYPixel;
twgl.m4.transformPoint(tm, dstPoint, dstPoint);
}

this._transformedHullDirty = false;

return this._transformedHullPoints;
}

/**
Expand Down

0 comments on commit a24929a

Please sign in to comment.