diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 1413a28..c5f3de6 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -24,6 +24,13 @@ this.scale = new math.Point(1, 1); /** + * The skew of the object. + * + * @member {Point} + */ + this.skew = new math.Point(0, 0); + + /** * The pivot point of the displayObject that it rotates around * * @member {Point} @@ -98,7 +105,8 @@ * @member {number} * @private */ - this._sr = 0; + this._srB = 0; + this._srC = 0; /** * cached cos rotation @@ -106,7 +114,8 @@ * @member {number} * @private */ - this._cr = 1; + this._crA = 1; + this._crD = 1; /** * The original, cached bounds of the object @@ -133,12 +142,20 @@ this._mask = null; /** - * Cached internal flag. + * Used internally to optimize updateTransform. * - * @member {boolean} + * @member {number} * @private */ - this._cacheIsDirty = false; + this._cachedRotX = 0; + + /** + * Used internally to optimize updateTransform. + * + * @member {number} + * @private + */ + this._cachedRotY = 0; } // constructor @@ -290,26 +307,35 @@ var wt = this.worldTransform; // temporary matrix variables - var a, b, c, d, tx, ty; + var a, b, c, d, tx, ty, + rotY = this.rotation + this.skew.y, + rotX = this.rotation + this.skew.x; // so if rotation is between 0 then we can simplify the multiplication process.. - if (this.rotation % math.PI_2) + if (rotY % math.PI_2 || rotX % math.PI_2) { // check to see if the rotation is the same as the previous render. This means we only need to use sin and cos when rotation actually changes - if (this.rotation !== this.rotationCache) + if (rotX !== this._cachedRotX || rotY !== this._cachedRotY) { - this.rotationCache = this.rotation; - this._sr = Math.sin(this.rotation); - this._cr = Math.cos(this.rotation); + // cache new values + this._cachedRotX = rotX; + this._cachedRotY = rotY; + + // recalculate expensive ops + this._crA = Math.cos(rotY); + this._srB = Math.sin(rotY); + + this._srC = Math.sin(-rotX); + this._crD = Math.cos(rotX); } // get the matrix values of the displayobject based on its transform properties.. - a = this._cr * this.scale.x; - b = this._sr * this.scale.x; - c = -this._sr * this.scale.y; - d = this._cr * this.scale.y; - tx = this.position.x; - ty = this.position.y; + a = this._crA * this.scale.x; + b = this._srB * this.scale.x; + c = this._srC * this.scale.y; + d = this._crD * this.scale.y; + tx = this.position.x; + ty = this.position.y; // check for pivot.. not often used so geared towards that fact! if (this.pivot.x || this.pivot.y) diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 1413a28..c5f3de6 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -24,6 +24,13 @@ this.scale = new math.Point(1, 1); /** + * The skew of the object. + * + * @member {Point} + */ + this.skew = new math.Point(0, 0); + + /** * The pivot point of the displayObject that it rotates around * * @member {Point} @@ -98,7 +105,8 @@ * @member {number} * @private */ - this._sr = 0; + this._srB = 0; + this._srC = 0; /** * cached cos rotation @@ -106,7 +114,8 @@ * @member {number} * @private */ - this._cr = 1; + this._crA = 1; + this._crD = 1; /** * The original, cached bounds of the object @@ -133,12 +142,20 @@ this._mask = null; /** - * Cached internal flag. + * Used internally to optimize updateTransform. * - * @member {boolean} + * @member {number} * @private */ - this._cacheIsDirty = false; + this._cachedRotX = 0; + + /** + * Used internally to optimize updateTransform. + * + * @member {number} + * @private + */ + this._cachedRotY = 0; } // constructor @@ -290,26 +307,35 @@ var wt = this.worldTransform; // temporary matrix variables - var a, b, c, d, tx, ty; + var a, b, c, d, tx, ty, + rotY = this.rotation + this.skew.y, + rotX = this.rotation + this.skew.x; // so if rotation is between 0 then we can simplify the multiplication process.. - if (this.rotation % math.PI_2) + if (rotY % math.PI_2 || rotX % math.PI_2) { // check to see if the rotation is the same as the previous render. This means we only need to use sin and cos when rotation actually changes - if (this.rotation !== this.rotationCache) + if (rotX !== this._cachedRotX || rotY !== this._cachedRotY) { - this.rotationCache = this.rotation; - this._sr = Math.sin(this.rotation); - this._cr = Math.cos(this.rotation); + // cache new values + this._cachedRotX = rotX; + this._cachedRotY = rotY; + + // recalculate expensive ops + this._crA = Math.cos(rotY); + this._srB = Math.sin(rotY); + + this._srC = Math.sin(-rotX); + this._crD = Math.cos(rotX); } // get the matrix values of the displayobject based on its transform properties.. - a = this._cr * this.scale.x; - b = this._sr * this.scale.x; - c = -this._sr * this.scale.y; - d = this._cr * this.scale.y; - tx = this.position.x; - ty = this.position.y; + a = this._crA * this.scale.x; + b = this._srB * this.scale.x; + c = this._srC * this.scale.y; + d = this._crD * this.scale.y; + tx = this.position.x; + ty = this.position.y; // check for pivot.. not often used so geared towards that fact! if (this.pivot.x || this.pivot.y) diff --git a/src/core/sprites/webgl/SpriteBatchRenderer.js b/src/core/sprites/webgl/SpriteBatchRenderer.js index 82a2318..ceb41f5 100644 --- a/src/core/sprites/webgl/SpriteBatchRenderer.js +++ b/src/core/sprites/webgl/SpriteBatchRenderer.js @@ -28,7 +28,7 @@ * * @member {number} */ - this.vertSize = 10; + this.vertSize = 12; /** * @@ -277,15 +277,21 @@ vertices[index++] = sprite.scale.x; vertices[index++] = sprite.scale.y; + //skew + vertices[index++] = sprite.skew.x; + vertices[index++] = sprite.skew.y; + //rotation vertices[index++] = sprite.rotation; // uv vertices[index++] = uvs.x0; vertices[index++] = uvs.y1; + // color vertices[index++] = sprite.alpha; + // ---- // xy vertices[index++] = w0; @@ -298,15 +304,21 @@ vertices[index++] = sprite.scale.x; vertices[index++] = sprite.scale.y; + //skew + vertices[index++] = sprite.skew.x; + vertices[index++] = sprite.skew.y; + //rotation vertices[index++] = sprite.rotation; // uv vertices[index++] = uvs.x1; vertices[index++] = uvs.y1; + // color vertices[index++] = sprite.alpha; + // ---- // xy vertices[index++] = w0; @@ -319,17 +331,21 @@ vertices[index++] = sprite.scale.x; vertices[index++] = sprite.scale.y; + //skew + vertices[index++] = sprite.skew.x; + vertices[index++] = sprite.skew.y; + //rotation vertices[index++] = sprite.rotation; // uv vertices[index++] = uvs.x2; vertices[index++] = uvs.y2; + // color vertices[index++] = sprite.alpha; - - + // ---- // xy vertices[index++] = w1; @@ -342,12 +358,17 @@ vertices[index++] = sprite.scale.x; vertices[index++] = sprite.scale.y; + //skew + vertices[index++] = sprite.skew.x; + vertices[index++] = sprite.skew.y; + //rotation vertices[index++] = sprite.rotation; // uv vertices[index++] = uvs.x3; vertices[index++] = uvs.y3; + // color vertices[index++] = sprite.alpha; @@ -438,7 +459,8 @@ gl.vertexAttribPointer(this.shader.attributes.aPositionCoord, 2, gl.FLOAT, false, stride, 5 * 4); gl.vertexAttribPointer(this.shader.attributes.aScale, 2, gl.FLOAT, false, stride, 7 * 4); - gl.vertexAttribPointer(this.shader.attributes.aRotation, 1, gl.FLOAT, false, stride, 9 * 4); + gl.vertexAttribPointer(this.shader.attributes.aSkew, 2, gl.FLOAT, false, stride, 9 * 4); + gl.vertexAttribPointer(this.shader.attributes.aRotation, 1, gl.FLOAT, false, stride, 11 * 4); }; /** diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 1413a28..c5f3de6 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -24,6 +24,13 @@ this.scale = new math.Point(1, 1); /** + * The skew of the object. + * + * @member {Point} + */ + this.skew = new math.Point(0, 0); + + /** * The pivot point of the displayObject that it rotates around * * @member {Point} @@ -98,7 +105,8 @@ * @member {number} * @private */ - this._sr = 0; + this._srB = 0; + this._srC = 0; /** * cached cos rotation @@ -106,7 +114,8 @@ * @member {number} * @private */ - this._cr = 1; + this._crA = 1; + this._crD = 1; /** * The original, cached bounds of the object @@ -133,12 +142,20 @@ this._mask = null; /** - * Cached internal flag. + * Used internally to optimize updateTransform. * - * @member {boolean} + * @member {number} * @private */ - this._cacheIsDirty = false; + this._cachedRotX = 0; + + /** + * Used internally to optimize updateTransform. + * + * @member {number} + * @private + */ + this._cachedRotY = 0; } // constructor @@ -290,26 +307,35 @@ var wt = this.worldTransform; // temporary matrix variables - var a, b, c, d, tx, ty; + var a, b, c, d, tx, ty, + rotY = this.rotation + this.skew.y, + rotX = this.rotation + this.skew.x; // so if rotation is between 0 then we can simplify the multiplication process.. - if (this.rotation % math.PI_2) + if (rotY % math.PI_2 || rotX % math.PI_2) { // check to see if the rotation is the same as the previous render. This means we only need to use sin and cos when rotation actually changes - if (this.rotation !== this.rotationCache) + if (rotX !== this._cachedRotX || rotY !== this._cachedRotY) { - this.rotationCache = this.rotation; - this._sr = Math.sin(this.rotation); - this._cr = Math.cos(this.rotation); + // cache new values + this._cachedRotX = rotX; + this._cachedRotY = rotY; + + // recalculate expensive ops + this._crA = Math.cos(rotY); + this._srB = Math.sin(rotY); + + this._srC = Math.sin(-rotX); + this._crD = Math.cos(rotX); } // get the matrix values of the displayobject based on its transform properties.. - a = this._cr * this.scale.x; - b = this._sr * this.scale.x; - c = -this._sr * this.scale.y; - d = this._cr * this.scale.y; - tx = this.position.x; - ty = this.position.y; + a = this._crA * this.scale.x; + b = this._srB * this.scale.x; + c = this._srC * this.scale.y; + d = this._crD * this.scale.y; + tx = this.position.x; + ty = this.position.y; // check for pivot.. not often used so geared towards that fact! if (this.pivot.x || this.pivot.y) diff --git a/src/core/sprites/webgl/SpriteBatchRenderer.js b/src/core/sprites/webgl/SpriteBatchRenderer.js index 82a2318..ceb41f5 100644 --- a/src/core/sprites/webgl/SpriteBatchRenderer.js +++ b/src/core/sprites/webgl/SpriteBatchRenderer.js @@ -28,7 +28,7 @@ * * @member {number} */ - this.vertSize = 10; + this.vertSize = 12; /** * @@ -277,15 +277,21 @@ vertices[index++] = sprite.scale.x; vertices[index++] = sprite.scale.y; + //skew + vertices[index++] = sprite.skew.x; + vertices[index++] = sprite.skew.y; + //rotation vertices[index++] = sprite.rotation; // uv vertices[index++] = uvs.x0; vertices[index++] = uvs.y1; + // color vertices[index++] = sprite.alpha; + // ---- // xy vertices[index++] = w0; @@ -298,15 +304,21 @@ vertices[index++] = sprite.scale.x; vertices[index++] = sprite.scale.y; + //skew + vertices[index++] = sprite.skew.x; + vertices[index++] = sprite.skew.y; + //rotation vertices[index++] = sprite.rotation; // uv vertices[index++] = uvs.x1; vertices[index++] = uvs.y1; + // color vertices[index++] = sprite.alpha; + // ---- // xy vertices[index++] = w0; @@ -319,17 +331,21 @@ vertices[index++] = sprite.scale.x; vertices[index++] = sprite.scale.y; + //skew + vertices[index++] = sprite.skew.x; + vertices[index++] = sprite.skew.y; + //rotation vertices[index++] = sprite.rotation; // uv vertices[index++] = uvs.x2; vertices[index++] = uvs.y2; + // color vertices[index++] = sprite.alpha; - - + // ---- // xy vertices[index++] = w1; @@ -342,12 +358,17 @@ vertices[index++] = sprite.scale.x; vertices[index++] = sprite.scale.y; + //skew + vertices[index++] = sprite.skew.x; + vertices[index++] = sprite.skew.y; + //rotation vertices[index++] = sprite.rotation; // uv vertices[index++] = uvs.x3; vertices[index++] = uvs.y3; + // color vertices[index++] = sprite.alpha; @@ -438,7 +459,8 @@ gl.vertexAttribPointer(this.shader.attributes.aPositionCoord, 2, gl.FLOAT, false, stride, 5 * 4); gl.vertexAttribPointer(this.shader.attributes.aScale, 2, gl.FLOAT, false, stride, 7 * 4); - gl.vertexAttribPointer(this.shader.attributes.aRotation, 1, gl.FLOAT, false, stride, 9 * 4); + gl.vertexAttribPointer(this.shader.attributes.aSkew, 2, gl.FLOAT, false, stride, 9 * 4); + gl.vertexAttribPointer(this.shader.attributes.aRotation, 1, gl.FLOAT, false, stride, 11 * 4); }; /** diff --git a/src/core/sprites/webgl/SpriteBatchShader.js b/src/core/sprites/webgl/SpriteBatchShader.js index 1f53252..f689d1c 100644 --- a/src/core/sprites/webgl/SpriteBatchShader.js +++ b/src/core/sprites/webgl/SpriteBatchShader.js @@ -18,6 +18,7 @@ 'attribute vec2 aPositionCoord;', 'attribute vec2 aScale;', + 'attribute vec2 aSkew;', 'attribute float aRotation;', 'uniform mat3 projectionMatrix;', @@ -33,8 +34,8 @@ 'void main(void){', ' vec2 v;', ' vec2 sv = aVertexPosition * aScale;', - ' v.x = (sv.x) * cos(aRotation) - (sv.y) * sin(aRotation);', - ' v.y = (sv.x) * sin(aRotation) + (sv.y) * cos(aRotation);', + ' v.x = (sv.x) * cos(aRotation + aSkew.y) - (sv.y) * sin(aRotation + aSkew.x);', + ' v.y = (sv.x) * sin(aRotation + aSkew.y) + (sv.y) * cos(aRotation + aSkew.x);', ' v = ( uMatrix * vec3(v + aPositionCoord , 1.0) ).xy ;', @@ -68,6 +69,7 @@ { aPositionCoord: 0, aScale: 0, + aSkew: 0, aRotation: 0 } );