Merge pull request #235 from mzgoddard/calc-transform-cache
Drawable _calculateTransform cache and inline work
This commit is contained in:
154
src/Drawable.js
154
src/Drawable.js
@@ -51,6 +51,12 @@ class Drawable {
|
||||
this._scale = twgl.v3.create(100, 100);
|
||||
this._direction = 90;
|
||||
this._transformDirty = true;
|
||||
this._rotationMatrix = twgl.m4.identity();
|
||||
this._rotationTransformDirty = true;
|
||||
this._rotationAdjusted = twgl.v3.create();
|
||||
this._rotationCenterDirty = true;
|
||||
this._skinScale = twgl.v3.create(0, 0, 0);
|
||||
this._skinScaleDirty = true;
|
||||
this._inverseMatrix = twgl.m4.identity();
|
||||
this._inverseTransformDirty = true;
|
||||
this._visible = true;
|
||||
@@ -156,6 +162,7 @@ class Drawable {
|
||||
}
|
||||
if ('direction' in properties && this._direction !== properties.direction) {
|
||||
this._direction = properties.direction;
|
||||
this._rotationTransformDirty = true;
|
||||
dirty = true;
|
||||
}
|
||||
if ('scale' in properties && (
|
||||
@@ -163,6 +170,8 @@ class Drawable {
|
||||
this._scale[1] !== properties.scale[1])) {
|
||||
this._scale[0] = properties.scale[0];
|
||||
this._scale[1] = properties.scale[1];
|
||||
this._rotationCenterDirty = true;
|
||||
this._skinScaleDirty = true;
|
||||
dirty = true;
|
||||
}
|
||||
if ('visible' in properties) {
|
||||
@@ -197,26 +206,141 @@ class Drawable {
|
||||
* @private
|
||||
*/
|
||||
_calculateTransform () {
|
||||
const modelMatrix = this._uniforms.u_modelMatrix;
|
||||
if (this._rotationTransformDirty) {
|
||||
const rotation = (270 - this._direction) * Math.PI / 180;
|
||||
|
||||
twgl.m4.identity(modelMatrix);
|
||||
twgl.m4.translate(modelMatrix, this._position, modelMatrix);
|
||||
// Calling rotationZ sets the destination matrix to a rotation
|
||||
// around the Z axis setting matrix components 0, 1, 4 and 5 with
|
||||
// cosine and sine values of the rotation.
|
||||
// twgl.m4.rotationZ(rotation, this._rotationMatrix);
|
||||
|
||||
const rotation = (270 - this._direction) * Math.PI / 180;
|
||||
twgl.m4.rotateZ(modelMatrix, rotation, modelMatrix);
|
||||
// twgl assumes the last value set to the matrix was anything.
|
||||
// Drawable knows, it was another rotationZ matrix, so we can skip
|
||||
// assigning the values that will never change.
|
||||
const c = Math.cos(rotation);
|
||||
const s = Math.sin(rotation);
|
||||
this._rotationMatrix[0] = c;
|
||||
this._rotationMatrix[1] = s;
|
||||
// this._rotationMatrix[2] = 0;
|
||||
// this._rotationMatrix[3] = 0;
|
||||
this._rotationMatrix[4] = -s;
|
||||
this._rotationMatrix[5] = c;
|
||||
// this._rotationMatrix[6] = 0;
|
||||
// this._rotationMatrix[7] = 0;
|
||||
// this._rotationMatrix[8] = 0;
|
||||
// this._rotationMatrix[9] = 0;
|
||||
// this._rotationMatrix[10] = 1;
|
||||
// this._rotationMatrix[11] = 0;
|
||||
// this._rotationMatrix[12] = 0;
|
||||
// this._rotationMatrix[13] = 0;
|
||||
// this._rotationMatrix[14] = 0;
|
||||
// this._rotationMatrix[15] = 1;
|
||||
|
||||
this._rotationTransformDirty = false;
|
||||
}
|
||||
|
||||
// Adjust rotation center relative to the skin.
|
||||
let rotationAdjusted = twgl.v3.subtract(this.skin.rotationCenter, twgl.v3.divScalar(this.skin.size, 2));
|
||||
rotationAdjusted = twgl.v3.multiply(rotationAdjusted, this.scale);
|
||||
rotationAdjusted = twgl.v3.divScalar(rotationAdjusted, 100);
|
||||
rotationAdjusted[1] *= -1; // Y flipped to Scratch coordinate.
|
||||
rotationAdjusted[2] = 0; // Z coordinate is 0.
|
||||
if (this._rotationCenterDirty && this.skin !== null) {
|
||||
// twgl version of the following in function work.
|
||||
// let rotationAdjusted = twgl.v3.subtract(
|
||||
// this.skin.rotationCenter,
|
||||
// twgl.v3.divScalar(this.skin.size, 2, this._rotationAdjusted),
|
||||
// this._rotationAdjusted
|
||||
// );
|
||||
// rotationAdjusted = twgl.v3.multiply(
|
||||
// rotationAdjusted, this._scale, rotationAdjusted
|
||||
// );
|
||||
// rotationAdjusted = twgl.v3.divScalar(
|
||||
// rotationAdjusted, 100, rotationAdjusted
|
||||
// );
|
||||
// rotationAdjusted[1] *= -1; // Y flipped to Scratch coordinate.
|
||||
// rotationAdjusted[2] = 0; // Z coordinate is 0.
|
||||
|
||||
twgl.m4.translate(modelMatrix, rotationAdjusted, modelMatrix);
|
||||
// Locally assign rotationCenter and skinSize to keep from having
|
||||
// the Skin getter properties called twice while locally assigning
|
||||
// their components for readability.
|
||||
const rotationCenter = this.skin.rotationCenter;
|
||||
const skinSize = this.skin.size;
|
||||
const center0 = rotationCenter[0];
|
||||
const center1 = rotationCenter[1];
|
||||
const skinSize0 = skinSize[0];
|
||||
const skinSize1 = skinSize[1];
|
||||
const scale0 = this._scale[0];
|
||||
const scale1 = this._scale[1];
|
||||
|
||||
const scaledSize = twgl.v3.divScalar(twgl.v3.multiply(this.skin.size, this._scale), 100);
|
||||
scaledSize[2] = 0; // was NaN because the vectors have only 2 components.
|
||||
twgl.m4.scale(modelMatrix, scaledSize, modelMatrix);
|
||||
const rotationAdjusted = this._rotationAdjusted;
|
||||
rotationAdjusted[0] = (center0 - (skinSize0 / 2)) * scale0 / 100;
|
||||
rotationAdjusted[1] = ((center1 - (skinSize1 / 2)) * scale1 / 100) * -1;
|
||||
// rotationAdjusted[2] = 0;
|
||||
|
||||
this._rotationCenterDirty = false;
|
||||
}
|
||||
|
||||
if (this._skinScaleDirty && this.skin !== null) {
|
||||
// twgl version of the following in function work.
|
||||
// const scaledSize = twgl.v3.divScalar(
|
||||
// twgl.v3.multiply(this.skin.size, this._scale),
|
||||
// 100
|
||||
// );
|
||||
// // was NaN because the vectors have only 2 components.
|
||||
// scaledSize[2] = 0;
|
||||
|
||||
// Locally assign skinSize to keep from having the Skin getter
|
||||
// properties called twice.
|
||||
const skinSize = this.skin.size;
|
||||
const scaledSize = this._skinScale;
|
||||
scaledSize[0] = skinSize[0] * this._scale[0] / 100;
|
||||
scaledSize[1] = skinSize[1] * this._scale[1] / 100;
|
||||
// scaledSize[2] = 0;
|
||||
|
||||
this._skinScaleDirty = false;
|
||||
}
|
||||
|
||||
const modelMatrix = this._uniforms.u_modelMatrix;
|
||||
|
||||
// twgl version of the following in function work.
|
||||
// twgl.m4.identity(modelMatrix);
|
||||
// twgl.m4.translate(modelMatrix, this._position, modelMatrix);
|
||||
// twgl.m4.multiply(modelMatrix, this._rotationMatrix, modelMatrix);
|
||||
// twgl.m4.translate(modelMatrix, this._rotationAdjusted, modelMatrix);
|
||||
// twgl.m4.scale(modelMatrix, scaledSize, modelMatrix);
|
||||
|
||||
// Drawable configures a 3D matrix for drawing in WebGL, but most values
|
||||
// will never be set because the inputs are on the X and Y position axis
|
||||
// and the Z rotation axis. Drawable can bring the work inside
|
||||
// _calculateTransform and greatly reduce the ammount of math and array
|
||||
// assignments needed.
|
||||
|
||||
const scale0 = this._skinScale[0];
|
||||
const scale1 = this._skinScale[1];
|
||||
const rotation00 = this._rotationMatrix[0];
|
||||
const rotation01 = this._rotationMatrix[1];
|
||||
const rotation10 = this._rotationMatrix[4];
|
||||
const rotation11 = this._rotationMatrix[5];
|
||||
const adjusted0 = this._rotationAdjusted[0];
|
||||
const adjusted1 = this._rotationAdjusted[1];
|
||||
const position0 = this._position[0];
|
||||
const position1 = this._position[1];
|
||||
|
||||
// Commented assignments show what the values are when the matrix was
|
||||
// instantiated. Those values will never change so they do not need to
|
||||
// be reassigned.
|
||||
modelMatrix[0] = scale0 * rotation00;
|
||||
modelMatrix[1] = scale0 * rotation01;
|
||||
// modelMatrix[2] = 0;
|
||||
// modelMatrix[3] = 0;
|
||||
modelMatrix[4] = scale1 * rotation10;
|
||||
modelMatrix[5] = scale1 * rotation11;
|
||||
// modelMatrix[6] = 0;
|
||||
// modelMatrix[7] = 0;
|
||||
// modelMatrix[8] = 0;
|
||||
// modelMatrix[9] = 0;
|
||||
// modelMatrix[10] = 1;
|
||||
// modelMatrix[11] = 0;
|
||||
modelMatrix[12] = (rotation00 * adjusted0) + (rotation10 * adjusted1) + position0;
|
||||
modelMatrix[13] = (rotation01 * adjusted0) + (rotation11 * adjusted1) + position1;
|
||||
// modelMatrix[14] = 0;
|
||||
// modelMatrix[15] = 1;
|
||||
|
||||
this._transformDirty = false;
|
||||
}
|
||||
@@ -369,6 +493,8 @@ class Drawable {
|
||||
* @private
|
||||
*/
|
||||
_skinWasAltered () {
|
||||
this._rotationCenterDirty = true;
|
||||
this._skinScaleDirty = true;
|
||||
this.setConvexHullDirty();
|
||||
this.setTransformDirty();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user